]> granicus.if.org Git - libvpx/commitdiff
wip: reuse mode/mv in multistream file
authorJohn Koleszar <jkoleszar@google.com>
Thu, 8 Mar 2012 20:18:10 +0000 (12:18 -0800)
committerJohn Koleszar <jkoleszar@google.com>
Sat, 10 Mar 2012 02:00:12 +0000 (18:00 -0800)
Add --read-mvinfo and --write-mvinfo to pass modes and motion vectors
between encodes

Change-Id: I8d73fbd43d27f765bb2ff3026f4a2191b81c46a9

vp8/common/blockd.h
vp8/encoder/encodeframe.c
vp8/encoder/onyx_if.c
vp8/encoder/onyx_int.h
vp8/encoder/rdopt.c
vp8/vp8_cx_iface.c
vp8/vp8_dx_iface.c
vpx/vp8cx.h
vpxenc.c

index ae32538fc4a48ff72301c0faceab82e30b6befab..cc6ee6ab183245fb57e080fae16ccbf0f74fd7ba 100644 (file)
@@ -205,6 +205,11 @@ typedef struct macroblockd
     DECLARE_ALIGNED(16, short,  dequant_y2[16]);
     DECLARE_ALIGNED(16, short,  dequant_uv[16]);
 
+    /* position of this macroblock */
+    int mbr;
+    int mbc;
+    int mbrc;
+
     /* 16 Y blocks, 4 U, 4 V, 1 DC 2nd order block, each with 16 entries. */
     BLOCKD block[25];
     int fullpixel_mask;
index 10f56078bac593d8871f1c9945abb204256f5114..c4bc9b090106348b2173cf0640853b044b63c9c1 100644 (file)
@@ -411,6 +411,10 @@ void encode_mb_row(VP8_COMP *cpi,
     // for each macroblock col in image
     for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
     {
+        xd->mbr = mb_row;
+        xd->mbc = mb_col;
+        xd->mbrc = mb_row * cm->mb_cols + mb_col;
+
         // Distance of Mb to the left & right edges, specified in
         // 1/8th pel units as they are always compared to values
         // that are in 1/8th pel units
@@ -1111,6 +1115,8 @@ extern int cnt_pm;
 
 extern void vp8_fix_contexts(MACROBLOCKD *x);
 
+#include "valgrind/memcheck.h"
+
 int vp8cx_encode_inter_macroblock
 (
     VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t,
@@ -1130,6 +1136,15 @@ int vp8cx_encode_inter_macroblock
     else
         x->encode_breakout = cpi->oxcf.encode_breakout;
 
+    if (cpi->external_modeinfo)
+    {
+        vp8_rd_use_external_mode(cpi, x, recon_yoffset, recon_uvoffset, &rate,
+                                 &distortion, &intra_error);
+        VALGRIND_CHECK_VALUE_IS_DEFINED(rate);
+        VALGRIND_CHECK_VALUE_IS_DEFINED(distortion);
+        VALGRIND_CHECK_VALUE_IS_DEFINED(intra_error);
+    }
+    else
     if (cpi->sf.RD)
     {
         int zbin_mode_boost_enabled = cpi->zbin_mode_boost_enabled;
index 57656bb4fc41d118730638f3e0e79418fec35d27..c8ccd051ef898e23e887bf9299c0a6e33a5782de 100644 (file)
@@ -859,7 +859,7 @@ void vp8_set_speed_features(VP8_COMP *cpi)
         {
             sf->auto_filter = 0;                     // Faster selection of loop filter
             sf->search_method = HEX;
-            sf->iterative_sub_pixel = 0;
+            //sf->iterative_sub_pixel = 0;
         }
 
         if (Speed > 6)
@@ -2449,7 +2449,7 @@ int vp8_use_as_reference(VP8_COMP *cpi, int ref_frame_flags)
 }
 int vp8_update_reference(VP8_COMP *cpi, int ref_frame_flags)
 {
-    if (ref_frame_flags > 7)
+    if (ref_frame_flags > 127)
         return -1 ;
 
     cpi->common.refresh_golden_frame = 0;
@@ -2465,6 +2465,8 @@ int vp8_update_reference(VP8_COMP *cpi, int ref_frame_flags)
     if (ref_frame_flags & VP8_ALT_FLAG)
         cpi->common.refresh_alt_ref_frame = 1;
 
+    cpi->common.copy_buffer_to_gf = (ref_frame_flags >> 3) & 3;
+    cpi->common.copy_buffer_to_arf = (ref_frame_flags >> 5) & 3;
     return 0;
 }
 
@@ -3187,8 +3189,11 @@ static void encode_frame_to_data_rate
         cpi->per_frame_bandwidth  = (int)(cpi->target_bandwidth / cpi->output_frame_rate);
 
     // Default turn off buffer to buffer copying
+    if(!cpi->external_modeinfo)
+    {
     cm->copy_buffer_to_gf = 0;
     cm->copy_buffer_to_arf = 0;
+    }
 
     // Clear zbin over-quant value and mode boost values.
     cpi->zbin_over_quant = 0;
@@ -4063,10 +4068,14 @@ static void encode_frame_to_data_rate
     // For inter frames the current default behavior is that when
     // cm->refresh_golden_frame is set we copy the old GF over to the ARF buffer
     // This is purely an encoder decision at present.
-    if (!cpi->oxcf.error_resilient_mode && cm->refresh_golden_frame)
+    if(!cpi->external_modeinfo)
+    {
+    if (!cpi->oxcf.error_resilient_mode && cm->refresh_golden_frame
+        && !cm->refresh_alt_ref_frame)
         cm->copy_buffer_to_arf  = 2;
     else
         cm->copy_buffer_to_arf  = 0;
+    }
 
     cm->frame_to_show = &cm->yv12_fb[cm->new_fb_idx];
 
index 6920fc316f9823c0213b310078b55eec608cd6cd..19e9ebe6582f7a86709171fc927d8d5ce53ec88e 100644 (file)
@@ -678,7 +678,7 @@ typedef struct VP8_COMP
     /* Number of MBs per row at lower-resolution level */
     int    mr_low_res_mb_cols;
 #endif
-
+    MODE_INFO *external_modeinfo;
 } VP8_COMP;
 
 void control_data_rate(VP8_COMP *cpi);
index 433412d730520d09c52b75ad5b01541ce407b0e4..f04ec521d320f43bc8007d8fba1d9985d5b2acab 100644 (file)
@@ -33,6 +33,7 @@
 #include "rdopt.h"
 #include "vpx_mem/vpx_mem.h"
 #include "vp8/common/systemdependent.h"
+#include "valgrind/memcheck.h"
 
 extern void vp8_update_zbin_extra(VP8_COMP *cpi, MACROBLOCK *x);
 
@@ -735,11 +736,12 @@ static int rd_pick_intra4x4mby_modes(VP8_COMP *cpi, MACROBLOCK *mb, int *Rate,
             break;
     }
 
+    VALGRIND_CHECK_VALUE_IS_DEFINED(tot_rate_y);
+    VALGRIND_CHECK_VALUE_IS_DEFINED(total_rd);
     if(total_rd >= (int64_t)best_rd)
         return INT_MAX;
-
     *Rate = cost;
-    *rate_y += tot_rate_y;
+    *rate_y = tot_rate_y;
     *Distortion = distortion;
 
     return RDCOST(mb->rdmult, mb->rddiv, cost, distortion);
@@ -1709,6 +1711,555 @@ static void rd_update_mvcount(VP8_COMP *cpi, MACROBLOCK *x, int_mv *best_ref_mv)
     }
 }
 
+#if 0
+void vp8_rd_use_external_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
+                            int recon_uvoffset, int *returnrate,
+                            int *returndistortion, int *returnintra)
+{
+    unsigned char *plane[4][3];
+    MODE_INFO *mi;
+    int rate, rate_y, rate_uv;
+    int distortion, distortion_y, distortion_uv;
+
+
+    mi = cpi->external_modeinfo + x->e_mbd.mbrc;
+    *x->e_mbd.mode_info_context = *mi;
+
+    /* Map partitioning info */
+    if(mi->mbmi.mode == SPLITMV)
+    {
+        int i;
+
+        x->partition_info->count = vp8_mbsplit_count[mi->mbmi.partitioning];
+
+        for (i = 0; i < x->partition_info->count; i++)
+        {
+            int j;
+
+            j = vp8_mbsplit_offset[mi->mbmi.partitioning][i];
+
+            /* TODO: this is mapping a union onto a struct, assume the
+             * data will never be looked at from the wrong context.
+             */
+            x->partition_info->bmi[i].mode = NEW4X4; //mi->bmi[j].as_mode;
+            x->partition_info->bmi[i].mv.as_int = mi->bmi[j].mv.as_int;
+        }
+        /*
+         * used to set x->e_mbd.mode_info_context->mbmi.mv.as_int
+         */
+        x->partition_info->bmi[15].mv.as_int = mi->bmi[15].mv.as_int;
+    }
+
+    rate = x->mbmode_cost[x->e_mbd.frame_type][mi->mbmi.mode];
+    rate += x->ref_frame_cost[mi->mbmi.ref_frame];
+    if(mi->mbmi.ref_frame == INTRA_FRAME)
+    {
+        vp8_build_intra_predictors_mby(&x->e_mbd);
+        macro_block_yrd(x, &rate_y, &distortion);
+        //hack
+        rate_uv = rate_y/4;
+        distortion_uv = distortion_y/4;
+    }
+    else
+    {
+        int sign_bias;
+        int_mv best_ref_mv_sb[2];
+        int_mv mode_mv_sb[2][MB_MODE_COUNT];
+        int_mv best_ref_mv;
+        int mdcounts[4];
+
+        get_predictor_pointers(cpi, plane, recon_yoffset, recon_uvoffset);
+        x->e_mbd.pre.y_buffer = plane[mi->mbmi.ref_frame][0];
+        x->e_mbd.pre.u_buffer = plane[mi->mbmi.ref_frame][1];
+        x->e_mbd.pre.v_buffer = plane[mi->mbmi.ref_frame][2];
+
+        /* Get nearby MV info */
+        sign_bias = vp8_find_near_mvs_bias(&x->e_mbd,
+                                           x->e_mbd.mode_info_context,
+                                           mode_mv_sb,
+                                           best_ref_mv_sb,
+                                           mdcounts,
+                                           mi->mbmi.ref_frame,
+                                           cpi->common.ref_frame_sign_bias);
+        best_ref_mv.as_int = best_ref_mv_sb[sign_bias].as_int;
+
+        if(mi->mbmi.mode != ZEROMV)
+            rate += vp8_mv_bit_cost(&mi->mbmi.mv, &best_ref_mv, x->mvcost, 96);
+        rate += vp8_cost_mv_ref(mi->mbmi.mode, mdcounts);
+
+        vp8_build_inter16x16_predictors_mby(&x->e_mbd, x->e_mbd.predictor, 16);
+        //rate += vp8_cost_mv_ref(mi->mbmi.mode, mdcounts);
+
+        // Y cost and distortion
+        macro_block_yrd(x, &rate_y, &distortion_y);
+
+        // UV cost and distortion
+        rd_inter16x16_uv(cpi, x, &rate_uv, &distortion_uv,
+                         cpi->common.full_pixel);
+    }
+
+    /* Test for skip blocks */
+    if (cpi->common.mb_no_coeff_skip)
+    {
+        int i, bit=1;
+
+        for(i=0; i<24; i++)
+            if(x->e_mbd.eobs[i])
+            {
+                bit = 0;
+                break;
+            }
+        if(bit)
+        {
+            rate_y = 0;
+            rate_uv = 0;
+        }
+        rate += vp8_cost_bit(cpi->prob_skip_false, bit);
+    }
+
+    *returnrate = rate + rate_y + rate_uv;
+    *returndistortion = distortion + distortion_y + distortion_uv;
+    *returnintra = (mi->mbmi.ref_frame == INTRA_FRAME)
+                   ? *returndistortion : INT_MAX;
+}
+#else
+void vp8_rd_use_external_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
+                            int recon_uvoffset, int *returnrate,
+                            int *returndistortion, int *returnintra)
+{
+    MODE_INFO *mi = cpi->external_modeinfo + x->e_mbd.mbrc;
+    BLOCK *b = &x->block[0];
+    BLOCKD *d = &x->e_mbd.block[0];
+    MACROBLOCKD *xd = &x->e_mbd;
+    union b_mode_info best_bmodes[16];
+    MB_MODE_INFO best_mbmode;
+    PARTITION_INFO best_partition;
+    int_mv best_ref_mv_sb[2];
+    int_mv mode_mv_sb[2][MB_MODE_COUNT];
+    int_mv best_ref_mv;
+    int_mv *mode_mv;
+    MB_PREDICTION_MODE this_mode;
+    int num00;
+
+    int i;
+    int mdcounts[4];
+    int rate=0;
+    int distortion=0;
+    int best_rd = INT_MAX;
+    int rate2, distortion2;
+    int uv_intra_rate, uv_intra_distortion, uv_intra_rate_tokenonly;
+    int rate_y, UNINITIALIZED_IS_SAFE(rate_uv);
+    int distortion_uv;
+    int best_yrd = INT_MAX;
+
+    MB_PREDICTION_MODE uv_intra_mode;
+    int_mv mvp;
+    int near_sadidx[8] = {0, 1, 2, 3, 4, 5, 6, 7};
+    int saddone=0;
+    int sr=0;    //search range got from mv_pred(). It uses step_param levels. (0-7)
+
+    unsigned char *plane[4][3];
+    int sign_bias = 0;
+
+    mode_mv = mode_mv_sb[sign_bias];
+    best_ref_mv.as_int = 0;
+    vpx_memset(mode_mv_sb, 0, sizeof(mode_mv_sb));
+    vpx_memset(&best_mbmode, 0, sizeof(best_mbmode));
+    vpx_memset(&best_bmodes, 0, sizeof(best_bmodes));
+
+    {
+        sign_bias = vp8_find_near_mvs_bias(&x->e_mbd,
+                                           x->e_mbd.mode_info_context,
+                                           mode_mv_sb,
+                                           best_ref_mv_sb,
+                                           mdcounts,
+                                           LAST_FRAME,
+                                           cpi->common.ref_frame_sign_bias);
+
+        mode_mv = mode_mv_sb[sign_bias];
+        best_ref_mv.as_int = best_ref_mv_sb[sign_bias].as_int;
+    }
+
+    cpi->ref_frame_flags|=0x7;
+    get_predictor_pointers(cpi, plane, recon_yoffset, recon_uvoffset);
+
+    *returnintra = INT_MAX;
+    cpi->mbs_tested_so_far++;          // Count of the number of MBs tested so far this frame
+
+    x->skip = 0;
+
+    x->e_mbd.mode_info_context->mbmi.ref_frame = INTRA_FRAME;
+    rd_pick_intra_mbuv_mode(cpi, x, &uv_intra_rate, &uv_intra_rate_tokenonly, &uv_intra_distortion);
+    uv_intra_mode = x->e_mbd.mode_info_context->mbmi.uv_mode;
+
+    {
+        int this_rd = INT_MAX;
+        int disable_skip = 0;
+        int other_cost = 0;
+        int this_ref_frame;
+
+        // These variables hold are rolling total cost and distortion for this mode
+        rate2 = 0;
+        distortion2 = 0;
+
+        this_mode = mi->mbmi.mode; //JRK
+        this_ref_frame = mi->mbmi.ref_frame;
+
+        x->e_mbd.mode_info_context->mbmi.mode = this_mode;
+        x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
+        x->e_mbd.mode_info_context->mbmi.ref_frame = this_ref_frame;
+
+        /* everything but intra */
+        if (x->e_mbd.mode_info_context->mbmi.ref_frame)
+        {
+            x->e_mbd.pre.y_buffer = plane[this_ref_frame][0];
+            x->e_mbd.pre.u_buffer = plane[this_ref_frame][1];
+            x->e_mbd.pre.v_buffer = plane[this_ref_frame][2];
+
+            if (sign_bias != cpi->common.ref_frame_sign_bias[this_ref_frame])
+            {
+                sign_bias = cpi->common.ref_frame_sign_bias[this_ref_frame];
+                mode_mv = mode_mv_sb[sign_bias];
+                best_ref_mv.as_int = best_ref_mv_sb[sign_bias].as_int;
+            }
+        }
+
+        // Experimental code. Special case for gf and arf zeromv modes. Increase zbin size to supress noise
+        if (cpi->zbin_mode_boost_enabled)
+        {
+            if ( this_ref_frame == INTRA_FRAME )
+                cpi->zbin_mode_boost = 0;
+            else
+            {
+                if (this_mode == ZEROMV)
+                {
+                    if (this_ref_frame != LAST_FRAME)
+                        cpi->zbin_mode_boost = GF_ZEROMV_ZBIN_BOOST;
+                    else
+                        cpi->zbin_mode_boost = LF_ZEROMV_ZBIN_BOOST;
+                }
+                else if (this_mode == SPLITMV)
+                    cpi->zbin_mode_boost = 0;
+                else
+                    cpi->zbin_mode_boost = MV_ZBIN_BOOST;
+            }
+
+            vp8_update_zbin_extra(cpi, x);
+        }
+
+        VALGRIND_CHECK_VALUE_IS_DEFINED(rate2);
+        switch (this_mode)
+        {
+        case B_PRED:
+        {
+            int tmp_rd;
+
+            // Note the rate value returned here includes the cost of coding the BPRED mode : x->mbmode_cost[x->e_mbd.frame_type][BPRED];
+            tmp_rd = rd_pick_intra4x4mby_modes(cpi, x, &rate, &rate_y, &distortion, INT_MAX);
+            VALGRIND_CHECK_VALUE_IS_DEFINED(rate);
+            VALGRIND_CHECK_VALUE_IS_DEFINED(rate_y);
+            VALGRIND_CHECK_VALUE_IS_DEFINED(distortion);
+            rate2 += rate;
+            distortion2 += distortion;
+
+            if(tmp_rd < best_yrd)
+            {
+                rate2 += uv_intra_rate;
+                rate_uv = uv_intra_rate_tokenonly;
+                distortion2 += uv_intra_distortion;
+                distortion_uv = uv_intra_distortion;
+            }
+            else
+            {
+                this_rd = INT_MAX;
+                disable_skip = 1;
+            }
+        }
+        break;
+
+        case SPLITMV:
+        {
+            int tmp_rd;
+            int this_rd_thresh;
+
+            //this_rd_thresh = (this_ref_frame == 1) ? cpi->rd_threshes[THR_NEW1] : cpi->rd_threshes[THR_NEW3];
+            //this_rd_thresh = (this_ref_frame == 2) ? cpi->rd_threshes[THR_NEW2] : this_rd_thresh;
+            this_rd_thresh = 0;
+
+            tmp_rd = vp8_rd_pick_best_mbsegmentation(cpi, x, &best_ref_mv,
+                                                     best_yrd, mdcounts,
+                                                     &rate, &rate_y, &distortion, this_rd_thresh) ;
+
+            VALGRIND_CHECK_VALUE_IS_DEFINED(rate);
+            VALGRIND_CHECK_VALUE_IS_DEFINED(distortion);
+            rate2 += rate;
+            distortion2 += distortion;
+
+            // If even the 'Y' rd value of split is higher than best so far then dont bother looking at UV
+            if (tmp_rd < best_yrd)
+            {
+                // Now work out UV cost and add it in
+                rd_inter4x4_uv(cpi, x, &rate_uv, &distortion_uv, cpi->common.full_pixel);
+                rate2 += rate_uv;
+                distortion2 += distortion_uv;
+            }
+            else
+            {
+                this_rd = INT_MAX;
+                disable_skip = 1;
+            }
+        }
+        VALGRIND_CHECK_VALUE_IS_DEFINED(rate_y);
+        break;
+        case DC_PRED:
+        case V_PRED:
+        case H_PRED:
+        case TM_PRED:
+            x->e_mbd.mode_info_context->mbmi.ref_frame = INTRA_FRAME;
+            vp8_build_intra_predictors_mby
+                (&x->e_mbd);
+            macro_block_yrd(x, &rate_y, &distortion) ;
+            rate2 += rate_y;
+            distortion2 += distortion;
+            rate2 += x->mbmode_cost[x->e_mbd.frame_type][x->e_mbd.mode_info_context->mbmi.mode];
+            rate2 += uv_intra_rate;
+            rate_uv = uv_intra_rate_tokenonly;
+            distortion2 += uv_intra_distortion;
+            distortion_uv = uv_intra_distortion;
+        VALGRIND_CHECK_VALUE_IS_DEFINED(rate_y);
+            break;
+
+        case NEWMV:
+            mode_mv[NEWMV].as_int = mi->mbmi.mv.as_int;
+        case NEARESTMV:
+        case NEARMV:
+            // Clip "next_nearest" so that it does not extend to far out of image
+            vp8_clamp_mv2(&mode_mv[this_mode], xd);
+
+            // Do not bother proceeding if the vector (from newmv,nearest or near) is 0,0 as this should then be coded using the zeromv mode.
+            if (((this_mode == NEARMV) || (this_mode == NEARESTMV)) && (mode_mv[this_mode].as_int == 0))
+                this_mode = ZEROMV;
+
+        case ZEROMV:
+
+            // Trap vectors that reach beyond the UMV borders
+            // Note that ALL New MV, Nearest MV Near MV and Zero MV code drops through to this point
+            // because of the lack of break statements in the previous two cases.
+            if (((mode_mv[this_mode].as_mv.row >> 3) < x->mv_row_min) || ((mode_mv[this_mode].as_mv.row >> 3) > x->mv_row_max) ||
+                ((mode_mv[this_mode].as_mv.col >> 3) < x->mv_col_min) || ((mode_mv[this_mode].as_mv.col >> 3) > x->mv_col_max))
+                assert(0);
+
+            vp8_set_mbmode_and_mvs(x, this_mode, &mode_mv[this_mode]);
+            vp8_build_inter16x16_predictors_mby(&x->e_mbd, x->e_mbd.predictor, 16);
+
+            if (cpi->active_map_enabled && x->active_ptr[0] == 0) {
+                x->skip = 1;
+            }
+            else if (x->encode_breakout)
+            {
+                unsigned int sse;
+                unsigned int var;
+                int threshold = (xd->block[0].dequant[1]
+                            * xd->block[0].dequant[1] >>4);
+
+                if(threshold < x->encode_breakout)
+                    threshold = x->encode_breakout;
+
+                var = vp8_variance16x16
+                        (*(b->base_src), b->src_stride,
+                        x->e_mbd.predictor, 16, &sse);
+
+                if (sse < threshold)
+                {
+                     unsigned int q2dc = xd->block[24].dequant[0];
+                    /* If theres is no codeable 2nd order dc
+                       or a very small uniform pixel change change */
+                    if ((sse - var < q2dc * q2dc >>4) ||
+                        (sse /2 > var && sse-var < 64))
+                    {
+                        // Check u and v to make sure skip is ok
+                        int sse2=  VP8_UVSSE(x);
+                        if (sse2 * 2 < threshold)
+                        {
+                            x->skip = 1;
+                            distortion2 = sse + sse2;
+                            rate2 = 500;
+
+                            /* for best_yrd calculation */
+                            rate_uv = 0;
+                            distortion_uv = sse2;
+
+                            disable_skip = 1;
+                            this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
+
+                            break;
+                        }
+                    }
+                }
+            }
+
+
+            //intermodecost[mode_index] = vp8_cost_mv_ref(this_mode, mdcounts);   // Experimental debug code
+
+            // Add in the Mv/mode cost
+            rate2 += vp8_cost_mv_ref(this_mode, mdcounts);
+
+            // Y cost and distortion
+            macro_block_yrd(x, &rate_y, &distortion);
+            rate2 += rate_y;
+            distortion2 += distortion;
+
+            // UV cost and distortion
+            rd_inter16x16_uv(cpi, x, &rate_uv, &distortion_uv, cpi->common.full_pixel);
+            rate2 += rate_uv;
+            distortion2 += distortion_uv;
+            break;
+
+        default:
+            assert(0);
+        }
+        VALGRIND_CHECK_VALUE_IS_DEFINED(rate_y);
+
+        VALGRIND_CHECK_VALUE_IS_DEFINED(rate2);
+        // Where skip is allowable add in the default per mb cost for the no skip case.
+        // where we then decide to skip we have to delete this and replace it with the
+        // cost of signallying a skip
+        if (cpi->common.mb_no_coeff_skip)
+        {
+            other_cost += vp8_cost_bit(cpi->prob_skip_false, 0);
+            rate2 += other_cost;
+        }
+
+        /* Estimate the reference frame signaling cost and add it
+         * to the rolling cost variable.
+         */
+        rate2 +=
+            x->ref_frame_cost[x->e_mbd.mode_info_context->mbmi.ref_frame];
+
+        VALGRIND_CHECK_VALUE_IS_DEFINED(rate2);
+        VALGRIND_CHECK_VALUE_IS_DEFINED(rate_y);
+        VALGRIND_CHECK_VALUE_IS_DEFINED(rate_uv);
+        if (!disable_skip)
+        {
+            // Test for the condition where skip block will be activated because there are no non zero coefficients and make any necessary adjustment for rate
+            if (cpi->common.mb_no_coeff_skip)
+            {
+                int tteob;
+
+                tteob = 0;
+
+                for (i = 0; i <= 24; i++)
+                {
+                    tteob += x->e_mbd.eobs[i];
+                }
+
+                if (tteob == 0)
+                {
+                    rate2 -= (rate_y + rate_uv);
+                    //for best_yrd calculation
+                    rate_uv = 0;
+
+                    // Back out no skip flag costing and add in skip flag costing
+                    if (cpi->prob_skip_false)
+                    {
+                        int prob_skip_cost;
+
+                        prob_skip_cost = vp8_cost_bit(cpi->prob_skip_false, 1);
+                        prob_skip_cost -= vp8_cost_bit(cpi->prob_skip_false, 0);
+                        rate2 += prob_skip_cost;
+                        other_cost += prob_skip_cost;
+                    }
+                }
+            }
+            // Calculate the final RD estimate for this mode
+            this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
+        }
+
+        VALGRIND_CHECK_VALUE_IS_DEFINED(rate2);
+        // Keep record of best intra distortion
+        if (x->e_mbd.mode_info_context->mbmi.ref_frame == INTRA_FRAME)
+        {
+            *returnintra = distortion2 ;
+        }
+
+        // Did this mode help.. i.i is it the new best mode
+        {
+            if (this_mode <= B_PRED)
+            {
+                x->e_mbd.mode_info_context->mbmi.uv_mode = uv_intra_mode;
+                /* required for left and above block mv */
+                x->e_mbd.mode_info_context->mbmi.mv.as_int = 0;
+            }
+
+            other_cost +=
+            x->ref_frame_cost[x->e_mbd.mode_info_context->mbmi.ref_frame];
+
+            /* Calculate the final y RD estimate for this mode */
+            best_yrd = RDCOST(x->rdmult, x->rddiv, (rate2-rate_uv-other_cost),
+                              (distortion2-distortion_uv));
+
+            VALGRIND_CHECK_VALUE_IS_DEFINED(rate2);
+            *returnrate = rate2;
+            *returndistortion = distortion2;
+            best_rd = this_rd;
+            vpx_memcpy(&best_mbmode, &x->e_mbd.mode_info_context->mbmi, sizeof(MB_MODE_INFO));
+            vpx_memcpy(&best_partition, x->partition_info, sizeof(PARTITION_INFO));
+
+            if ((this_mode == B_PRED) || (this_mode == SPLITMV))
+                for (i = 0; i < 16; i++)
+                {
+                    best_bmodes[i] = x->e_mbd.block[i].bmi;
+                }
+        }
+    }
+
+    VALGRIND_CHECK_VALUE_IS_DEFINED(*returnrate);
+    VALGRIND_CHECK_VALUE_IS_DEFINED(*returndistortion);
+    VALGRIND_CHECK_VALUE_IS_DEFINED(*returnintra);
+
+    if (cpi->is_src_frame_alt_ref &&
+        (best_mbmode.mode != ZEROMV || best_mbmode.ref_frame != ALTREF_FRAME))
+    {
+        x->e_mbd.mode_info_context->mbmi.mode = ZEROMV;
+        x->e_mbd.mode_info_context->mbmi.ref_frame = ALTREF_FRAME;
+        x->e_mbd.mode_info_context->mbmi.mv.as_int = 0;
+        x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
+        x->e_mbd.mode_info_context->mbmi.mb_skip_coeff =
+                                        (cpi->common.mb_no_coeff_skip);
+        x->e_mbd.mode_info_context->mbmi.partitioning = 0;
+
+        return;
+    }
+
+
+    // macroblock modes
+    vpx_memcpy(&x->e_mbd.mode_info_context->mbmi, &best_mbmode, sizeof(MB_MODE_INFO));
+
+    if (best_mbmode.mode == B_PRED)
+    {
+        for (i = 0; i < 16; i++)
+            xd->mode_info_context->bmi[i].as_mode = best_bmodes[i].as_mode;
+    }
+
+    if (best_mbmode.mode == SPLITMV)
+    {
+        for (i = 0; i < 16; i++)
+            xd->mode_info_context->bmi[i].mv.as_int = best_bmodes[i].mv.as_int;
+
+        vpx_memcpy(x->partition_info, &best_partition, sizeof(PARTITION_INFO));
+
+        x->e_mbd.mode_info_context->mbmi.mv.as_int =
+                                      x->partition_info->bmi[15].mv.as_int;
+    }
+
+    if (sign_bias
+        != cpi->common.ref_frame_sign_bias[xd->mode_info_context->mbmi.ref_frame])
+        best_ref_mv.as_int = best_ref_mv_sb[!sign_bias].as_int;
+
+    rd_update_mvcount(cpi, x, &best_ref_mv);
+}
+#endif
+
 
 void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
                             int recon_uvoffset, int *returnrate,
index 31254d47b034e7be7acc9182da4044520930ed1b..108632c6b607b1db0831a3acd171b9a2a3f3b835 100644 (file)
@@ -996,6 +996,7 @@ static const vpx_codec_cx_pkt_t *vp8e_get_cxdata(vpx_codec_alg_priv_t  *ctx,
                                 + ctx->cpi->common.mode_info_stride
                                 * ctx->cx_data_iter.mode_info_row;
             pkt->data.raw.sz = sizeof(MODE_INFO) * ctx->cpi->common.mb_cols;
+
             ctx->cx_data_iter.mode_info_row++;
             return pkt;
         }
@@ -1218,6 +1219,38 @@ static vpx_codec_err_t vp8e_set_scalemode(vpx_codec_alg_priv_t *ctx,
 }
 
 
+static vpx_codec_err_t set_modeinfo(vpx_codec_alg_priv_t *ctx,
+        int ctr_id,
+        va_list args)
+{
+    vpx_fixed_buf_t *data =  va_arg(args, vpx_fixed_buf_t *);
+
+    ctx->cpi->external_modeinfo = data ? data->buf : NULL;
+    return VPX_CODEC_OK;
+}
+
+
+static vpx_codec_err_t vp8_get_last_ref_updates(vpx_codec_alg_priv_t *ctx,
+                                                int ctrl_id,
+                                                va_list args)
+{
+    int *update_info = va_arg(args, int *);
+    VP8_COMP *pbi = ctx->cpi;
+
+    if (update_info)
+    {
+        *update_info = pbi->common.refresh_alt_ref_frame * (int) VP8_ALTR_FRAME
+            + pbi->common.refresh_golden_frame * (int) VP8_GOLD_FRAME
+            + pbi->common.refresh_last_frame * (int) VP8_LAST_FRAME
+            + (pbi->common.copy_buffer_to_gf << 3)
+            + (pbi->common.copy_buffer_to_arf << 5);
+
+        return VPX_CODEC_OK;
+    }
+    else
+        return VPX_CODEC_INVALID_PARAM;
+}
+
 static vpx_codec_ctrl_fn_map_t vp8e_ctf_maps[] =
 {
     {VP8_SET_REFERENCE,                 vp8e_set_reference},
@@ -1244,6 +1277,8 @@ static vpx_codec_ctrl_fn_map_t vp8e_ctf_maps[] =
     {VP8E_SET_TUNING,                   set_param},
     {VP8E_SET_CQ_LEVEL,                 set_param},
     {VP8E_SET_MAX_INTRA_BITRATE_PCT,    set_param},
+    {VP8E_SET_MODEINFO,                 set_modeinfo},
+    {VP8E_GET_LAST_REF_UPDATES,         vp8_get_last_ref_updates},
     { -1, NULL},
 };
 
index 0a62d9717da6aad8f32adbb48cfb0591a76e8e43..276859d31c6b9ef059f4b06dd7f272d5384fb416 100644 (file)
@@ -692,7 +692,9 @@ static vpx_codec_err_t vp8_get_last_ref_updates(vpx_codec_alg_priv_t *ctx,
     {
         *update_info = pbi->common.refresh_alt_ref_frame * (int) VP8_ALTR_FRAME
             + pbi->common.refresh_golden_frame * (int) VP8_GOLD_FRAME
-            + pbi->common.refresh_last_frame * (int) VP8_LAST_FRAME;
+            + pbi->common.refresh_last_frame * (int) VP8_LAST_FRAME
+            + (pbi->common.copy_buffer_to_gf << 3)
+            + (pbi->common.copy_buffer_to_arf << 5);
 
         return VPX_CODEC_OK;
     }
index 52752832c2d55ae36f1abcaa3fd1aac7f45917ff..41b8fa59fe610796fe54d735aab3471f150e5798 100644 (file)
@@ -178,6 +178,10 @@ enum vp8e_enc_control_id
      *
      */
     VP8E_SET_MAX_INTRA_BITRATE_PCT,
+
+    /*!\brief Mode/mv data */
+    VP8E_SET_MODEINFO,
+    VP8E_GET_LAST_REF_UPDATES
 };
 
 /*!\brief vpx 1-D scaling mode
@@ -311,6 +315,8 @@ VPX_CTRL_USE_TYPE(VP8E_GET_LAST_QUANTIZER_64,  int *)
 
 VPX_CTRL_USE_TYPE(VP8E_SET_MAX_INTRA_BITRATE_PCT, unsigned int)
 
+VPX_CTRL_USE_TYPE(VP8E_SET_MODEINFO, vpx_fixed_buf_t *)
+VPX_CTRL_USE_TYPE(VP8E_GET_LAST_REF_UPDATES, int *)
 
 /*! @} - end defgroup vp8_encoder */
 #include "vpx_codec_impl_bottom.h"
index f2828657f5d71e9cdbf72efe6e657027fb6c3711..d8c4fd71a99ce1697c812ded8333347105885b4b 100644 (file)
--- a/vpxenc.c
+++ b/vpxenc.c
@@ -1182,12 +1182,17 @@ static const arg_def_t q_hist_n         = ARG_DEF(NULL, "q-hist", 1,
         "Show quantizer histogram (n-buckets)");
 static const arg_def_t rate_hist_n         = ARG_DEF(NULL, "rate-hist", 1,
         "Show rate histogram (n-buckets)");
+static const arg_def_t read_modemv_arg  = ARG_DEF(NULL, "read-modemv", 0,
+        "Read modes/mvs");
+static const arg_def_t write_modemv_arg  = ARG_DEF(NULL, "write-modemv", 0,
+        "Write modes/mvs");
 static const arg_def_t *main_args[] =
 {
     &debugmode,
     &outputfile, &codecarg, &passes, &pass_arg, &fpf_name, &limit, &deadline,
     &best_dl, &good_dl, &rt_dl,
     &verbosearg, &psnrarg, &use_ivf, &q_hist_n, &rate_hist_n,
+    &read_modemv_arg, &write_modemv_arg,
     NULL
 };
 
@@ -1693,6 +1698,8 @@ struct global_config
     int                       debug;
     int                       show_q_hist_buckets;
     int                       show_rate_hist_buckets;
+    int                       read_modemv;
+    int                       write_modemv;
 };
 
 
@@ -1808,6 +1815,10 @@ static void parse_global_config(struct global_config *global, char **argv)
             global->show_q_hist_buckets = arg_parse_uint(&arg);
         else if (arg_match(&arg, &rate_hist_n, argi))
             global->show_rate_hist_buckets = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &read_modemv_arg, argi))
+            global->read_modemv = 1;
+        else if (arg_match(&arg, &write_modemv_arg, argi))
+            global->write_modemv = 1;
         else
             argj++;
     }
@@ -2456,6 +2467,7 @@ struct link_record
     uint32_t sz;
     uint16_t w;
     uint16_t h;
+    int      refs_updated;
 };
 
 static void
@@ -2472,6 +2484,9 @@ write_multistream_file(struct stream_state  *streams,
     const struct vpx_codec_enc_cfg *cfg = &stream->config.cfg;
     struct link_record link = {0};
 
+    vpx_codec_control(&stream->encoder, VP8E_GET_LAST_REF_UPDATES, &link.refs_updated);
+    ctx_exit_on_error(&stream->encoder, "Failed to get refs");
+
     while ((pkt = vpx_codec_get_cx_data(&stream->encoder, &iter)))
     {
         *got_data = 1;
@@ -2596,6 +2611,38 @@ float usec_to_fps(uint64_t usec, unsigned int frames)
 }
 
 
+static void set_modeinfo(struct stream_state *stream,
+                         struct webm_ctx     *webm)
+{
+    unsigned char *ptr;
+    struct link_record link;
+    int again;
+    int refs=0;
+
+    vpx_codec_control(&stream->encoder, VP8E_SET_MODEINFO, NULL);
+    ptr = webm->buf + webm->buf_sz;
+    do
+    {
+        ptr -= sizeof(link);
+        memcpy(&link, ptr, sizeof(link));
+        again = link.sz >> 31;
+        link.sz &= ~(1<<31);
+        ptr -= link.sz;
+        if(link.w == stream->config.cfg.g_w
+           && link.h == stream->config.cfg.g_h)
+        {
+            vpx_fixed_buf_t modeinfo;
+
+            modeinfo.buf = ptr;
+            modeinfo.sz = link.sz;
+            vpx_codec_control(&stream->encoder, VP8E_SET_MODEINFO, &modeinfo);
+            vpx_codec_control(&stream->encoder, VP8E_UPD_REFERENCE, link.refs_updated);
+            ctx_exit_on_error(&stream->encoder, "Failed to set refs");
+            break;
+        }
+    } while(again);
+}
+
 int main(int argc, const char **argv_)
 {
     int                    pass;
@@ -2752,6 +2799,10 @@ int main(int argc, const char **argv_)
             else
                 frame_avail = 0;
 
+            /* Update mode/mv info if available */
+            if(input.file_type == FILE_TYPE_WEBM && global.read_modemv)
+                FOREACH_STREAM(set_modeinfo(stream, &input.webm));
+
             vpx_usec_timer_start(&timer);
             FOREACH_STREAM(encode_frame(stream, &global,
                                         frame_avail ? &raw : NULL,
@@ -2762,7 +2813,7 @@ int main(int argc, const char **argv_)
             FOREACH_STREAM(update_quantizer_histogram(stream));
 
             got_data = 0;
-            if(1)
+            if(global.write_modemv)
                 write_multistream_file(streams, &global, &got_data);
             else
                 FOREACH_STREAM(get_cx_data(stream, &global, &got_data));