Merge "Modify sub-pixel filters to eliminate unnecessary calculations"
diff --git a/build/make/configure.sh b/build/make/configure.sh
index b65f3b7..75279b9 100755
--- a/build/make/configure.sh
+++ b/build/make/configure.sh
@@ -78,6 +78,7 @@
   --log=yes|no|FILE           file configure log is written to [config.err]
   --target=TARGET             target platform tuple [generic-gnu]
   --cpu=CPU                   optimize for a specific cpu rather than a family
+  --extra-cflags=ECFLAGS      add ECFLAGS to CFLAGS [$CFLAGS]
   ${toggle_extra_warnings}    emit harmless warnings (always non-fatal)
   ${toggle_werror}            treat warnings as errors, if possible
                               (not available with all compilers)
@@ -442,6 +443,9 @@
         ;;
         --cpu=*) tune_cpu="$optval"
         ;;
+        --extra-cflags=*)
+        extra_cflags="${optval}"
+        ;;
         --enable-?*|--disable-?*)
         eval `echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g'`
         echo "${CMDLINE_SELECT} ${ARCH_EXT_LIST}" | grep "^ *$option\$" >/dev/null || die_unknown $opt
@@ -665,7 +669,7 @@
                 check_add_cflags -march=${tgt_isa}
                 check_add_asflags -march=${tgt_isa}
             fi
-
+            enabled debug && add_asflags -g
             asm_conversion_cmd="${source_path}/build/make/ads2gas.pl"
             ;;
         rvct)
@@ -690,6 +694,7 @@
             arch_int=${tgt_isa##armv}
             arch_int=${arch_int%%te}
             check_add_asflags --pd "\"ARCHITECTURE SETA ${arch_int}\""
+            enabled debug && add_asflags -g
         ;;
         esac
 
@@ -972,6 +977,10 @@
         add_cflags -D_LARGEFILE_SOURCE
         add_cflags -D_FILE_OFFSET_BITS=64
     fi
+
+    # append any user defined extra cflags
+    check_add_cflags ${extra_cflags} || \
+    die "Requested extra CFLAGS '${extra_cflags}' not supported by compiler"
 }
 
 process_toolchain() {
diff --git a/configure b/configure
index 5a502ae..cb568d7 100755
--- a/configure
+++ b/configure
@@ -300,7 +300,7 @@
         optval="${opt#*=}"
         case "$opt" in
         --disable-codecs) for c in ${CODECS}; do disable $c; done ;;
-        *) process_common_cmdline $opt
+        *) process_common_cmdline "$opt"
         ;;
         esac
     done
diff --git a/vp8/encoder/firstpass.c b/vp8/encoder/firstpass.c
index e5a22d9..a77ced7 100644
--- a/vp8/encoder/firstpass.c
+++ b/vp8/encoder/firstpass.c
@@ -1316,6 +1316,43 @@
 {
 }
 
+// This function gives and estimate of how badly we believe
+// the predicition quality is decaying from frame to frame.
+double gf_prediction_decay_rate(VP8_COMP *cpi, FIRSTPASS_STATS *next_frame)
+{
+    double prediction_decay_rate;
+    double motion_decay;
+    double motion_pct = next_frame->pcnt_motion;
+
+
+    // Initial basis is the % mbs inter coded
+    prediction_decay_rate = next_frame->pcnt_inter;
+
+    // High % motion -> somewhat higher decay rate
+    motion_decay = (1.0 - (motion_pct / 20.0));
+    if (motion_decay < prediction_decay_rate)
+        prediction_decay_rate = motion_decay;
+
+    // Adjustment to decay rate based on speed of motion
+    {
+        double this_mv_rabs;
+        double this_mv_cabs;
+        double distance_factor;
+
+        this_mv_rabs = fabs(next_frame->mvr_abs * motion_pct);
+        this_mv_cabs = fabs(next_frame->mvc_abs * motion_pct);
+
+        distance_factor = sqrt((this_mv_rabs * this_mv_rabs) +
+                               (this_mv_cabs * this_mv_cabs)) / 250.0;
+        distance_factor = ((distance_factor > 1.0)
+                                ? 0.0 : (1.0 - distance_factor));
+        if (distance_factor < prediction_decay_rate)
+            prediction_decay_rate = distance_factor;
+    }
+
+    return prediction_decay_rate;
+}
+
 // Analyse and define a gf/arf group .
 static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
 {
@@ -1337,17 +1374,20 @@
     double decay_accumulator = 1.0;
 
     double boost_factor = IIFACTOR;
-    double loop_decay_rate = 1.00;        // Starting decay rate
+    double loop_decay_rate = 1.00;          // Starting decay rate
 
     double this_frame_mv_in_out = 0.0;
     double mv_in_out_accumulator = 0.0;
     double abs_mv_in_out_accumulator = 0.0;
     double mod_err_per_mb_accumulator = 0.0;
 
-    int max_bits = frame_max_bits(cpi);    // Max for a single frame
+    int max_bits = frame_max_bits(cpi);     // Max for a single frame
 
     unsigned char *fpmm_pos;
 
+    unsigned int allow_alt_ref =
+                    cpi->oxcf.play_alternate && cpi->oxcf.lag_in_frames;
+
     cpi->gf_group_bits = 0;
     cpi->gf_decay_rate = 0;
 
@@ -1362,47 +1402,57 @@
     // Preload the stats for the next frame.
     mod_frame_err = calculate_modified_err(cpi, this_frame);
 
-    // Note the error of the frame at the start of the group (this will be the GF frame error if we code a normal gf
+    // Note the error of the frame at the start of the group (this will be
+    // the GF frame error if we code a normal gf
     gf_first_frame_err = mod_frame_err;
 
-    // Special treatment if the current frame is a key frame (which is also a gf).
-    // If it is then its error score (and hence bit allocation) need to be subtracted out
-    // from the calculation for the GF group
+    // Special treatment if the current frame is a key frame (which is also
+    // a gf). If it is then its error score (and hence bit allocation) need
+    // to be subtracted out from the calculation for the GF group
     if (cpi->common.frame_type == KEY_FRAME)
         gf_group_err -= gf_first_frame_err;
 
-    // Scan forward to try and work out how many frames the next gf group should contain and
-    // what level of boost is appropriate for the GF or ARF that will be coded with the group
+    // Scan forward to try and work out how many frames the next gf group
+    // should contain and what level of boost is appropriate for the GF
+    // or ARF that will be coded with the group
     i = 0;
 
-    while (((i < cpi->static_scene_max_gf_interval) || ((cpi->frames_to_key - i) < MIN_GF_INTERVAL)) && (i < cpi->frames_to_key))
+    while (((i < cpi->static_scene_max_gf_interval) ||
+            ((cpi->frames_to_key - i) < MIN_GF_INTERVAL)) &&
+           (i < cpi->frames_to_key))
     {
         double r;
         double this_frame_mvr_ratio;
         double this_frame_mvc_ratio;
         double motion_decay;
-        double motion_pct = next_frame.pcnt_motion;
+        //double motion_pct = next_frame.pcnt_motion;
+        double motion_pct;
 
-        i++;                                                    // Increment the loop counter
+        i++;    // Increment the loop counter
 
         // Accumulate error score of frames in this gf group
         mod_frame_err = calculate_modified_err(cpi, this_frame);
 
         gf_group_err += mod_frame_err;
 
-        mod_err_per_mb_accumulator += mod_frame_err / DOUBLE_DIVIDE_CHECK((double)cpi->common.MBs);
+        mod_err_per_mb_accumulator +=
+            mod_frame_err / DOUBLE_DIVIDE_CHECK((double)cpi->common.MBs);
 
         if (EOF == vp8_input_stats(cpi, &next_frame))
             break;
 
         // Accumulate motion stats.
+        motion_pct = next_frame.pcnt_motion;
         mv_accumulator_rabs += fabs(next_frame.mvr_abs * motion_pct);
         mv_accumulator_cabs += fabs(next_frame.mvc_abs * motion_pct);
 
         //Accumulate Motion In/Out of frame stats
-        this_frame_mv_in_out = next_frame.mv_in_out_count * next_frame.pcnt_motion;
-        mv_in_out_accumulator += next_frame.mv_in_out_count * next_frame.pcnt_motion;
-        abs_mv_in_out_accumulator += fabs(next_frame.mv_in_out_count * next_frame.pcnt_motion);
+        this_frame_mv_in_out =
+            next_frame.mv_in_out_count * motion_pct;
+        mv_in_out_accumulator +=
+            next_frame.mv_in_out_count * motion_pct;
+        abs_mv_in_out_accumulator +=
+            fabs(next_frame.mv_in_out_count * motion_pct);
 
         // If there is a significant amount of motion
         if (motion_pct > 0.05)
@@ -1431,7 +1481,9 @@
         }
 
         // Underlying boost factor is based on inter intra error ratio
-        r = (boost_factor * (next_frame.intra_error / DOUBLE_DIVIDE_CHECK(next_frame.coded_error)));
+        r = ( boost_factor *
+              ( next_frame.intra_error /
+                DOUBLE_DIVIDE_CHECK(next_frame.coded_error)));
 
         if (next_frame.intra_error > cpi->gf_intra_err_min)
             r = (IIKFACTOR2 * next_frame.intra_error /
@@ -1440,54 +1492,76 @@
             r = (IIKFACTOR2 * cpi->gf_intra_err_min /
                      DOUBLE_DIVIDE_CHECK(next_frame.coded_error));
 
-        // Increase boost for frames where new data coming into frame (eg zoom out)
-        // Slightly reduce boost if there is a net balance of motion out of the frame (zoom in)
+        // Increase boost for frames where new data coming into frame
+        // (eg zoom out). Slightly reduce boost if there is a net balance
+        // of motion out of the frame (zoom in).
         // The range for this_frame_mv_in_out is -1.0 to +1.0
         if (this_frame_mv_in_out > 0.0)
             r += r * (this_frame_mv_in_out * 2.0);
+        // In extreme case boost is halved
         else
-            r += r * (this_frame_mv_in_out / 2.0);  // In extreme case boost is halved
+            r += r * (this_frame_mv_in_out / 2.0);
 
         if (r > GF_RMAX)
             r = GF_RMAX;
 
-        // Adjust loop decay rate
-        //if ( next_frame.pcnt_inter < loop_decay_rate )
-        loop_decay_rate = next_frame.pcnt_inter;
-
-        // High % motion -> somewhat higher decay rate
-        motion_decay = (1.0 - (motion_pct / 20.0));
-        if (motion_decay < loop_decay_rate)
-            loop_decay_rate = motion_decay;
-
-        // Adjustment to decay rate based on speed of motion
-        {
-            double this_mv_rabs;
-            double this_mv_cabs;
-            double distance_factor;
-
-            this_mv_rabs = fabs(next_frame.mvr_abs * motion_pct);
-            this_mv_cabs = fabs(next_frame.mvc_abs * motion_pct);
-
-            distance_factor = sqrt((this_mv_rabs * this_mv_rabs) +
-                                   (this_mv_cabs * this_mv_cabs)) / 250.0;
-            distance_factor = ((distance_factor > 1.0)
-                                    ? 0.0 : (1.0 - distance_factor));
-            if (distance_factor < loop_decay_rate)
-                loop_decay_rate = distance_factor;
-        }
+        loop_decay_rate = gf_prediction_decay_rate(cpi, &next_frame);
 
         // Cumulative effect of decay
         decay_accumulator = decay_accumulator * loop_decay_rate;
         decay_accumulator = decay_accumulator < 0.1 ? 0.1 : decay_accumulator;
-        //decay_accumulator = ( loop_decay_rate < decay_accumulator ) ? loop_decay_rate : decay_accumulator;
 
         boost_score += (decay_accumulator * r);
 
+        // Break clause to detect very still sections after motion
+        // For example a staic image after a fade or other transition
+        // instead of a clean key frame.
+        if ( (i > MIN_GF_INTERVAL) &&
+             (loop_decay_rate >= 0.999) &&
+             (decay_accumulator < 0.9) )
+        {
+            int j;
+            FIRSTPASS_STATS * position = cpi->stats_in;
+            FIRSTPASS_STATS tmp_next_frame;
+            double decay_rate;
+
+            // Look ahead a few frames to see if static condition
+            // persists...
+            for ( j = 0; j < 4; j++ )
+            {
+                if (EOF == vp8_input_stats(cpi, &tmp_next_frame))
+                    break;
+
+                decay_rate = gf_prediction_decay_rate(cpi, &tmp_next_frame);
+                if ( decay_rate < 0.999 )
+                    break;
+            }
+            reset_fpf_position(cpi, position);            // Reset file position
+
+            // Force GF not alt ref
+            if ( j == 4 )
+            {
+                if (0)
+                {
+                    FILE *f = fopen("fadegf.stt", "a");
+                    fprintf(f, " %8d %8d %10.4f %10.4f %10.4f\n",
+                         cpi->common.current_video_frame+i, i,
+                         loop_decay_rate, decay_accumulator,
+                         boost_score );
+                    fclose(f);
+                }
+
+                allow_alt_ref = FALSE;
+
+                boost_score = old_boost_score;
+                break;
+            }
+        }
+
         // Break out conditions.
         if  (   /* i>4 || */
             // Break at cpi->max_gf_interval unless almost totally static
-            (i >= cpi->max_gf_interval && (decay_accumulator < 0.99)) ||
+            (i >= cpi->max_gf_interval && (decay_accumulator < 0.995)) ||
             (
                 // Dont break out with a very short interval
                 (i > MIN_GF_INTERVAL) &&
@@ -1509,7 +1583,8 @@
         old_boost_score = boost_score;
     }
 
-    cpi->gf_decay_rate = (i > 0) ? (int)(100.0 * (1.0 - decay_accumulator)) / i : 0;
+    cpi->gf_decay_rate =
+        (i > 0) ? (int)(100.0 * (1.0 - decay_accumulator)) / i : 0;
 
     // When using CBR apply additional buffer related upper limits
     if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
@@ -1519,7 +1594,8 @@
         // For cbr apply buffer related limits
         if (cpi->drop_frames_allowed)
         {
-            int df_buffer_level = cpi->oxcf.drop_frames_water_mark * (cpi->oxcf.optimal_buffer_level / 100);
+            int df_buffer_level = cpi->oxcf.drop_frames_water_mark *
+                                  (cpi->oxcf.optimal_buffer_level / 100);
 
             if (cpi->buffer_level > df_buffer_level)
                 max_boost = ((double)((cpi->buffer_level - df_buffer_level) * 2 / 3) * 16.0) / DOUBLE_DIVIDE_CHECK((double)cpi->av_per_frame_bandwidth);
@@ -1542,10 +1618,10 @@
     cpi->gfu_boost = (int)(boost_score * 100.0) >> 4;
 
     // Should we use the alternate refernce frame
-    if (cpi->oxcf.play_alternate &&
-        cpi->oxcf.lag_in_frames &&
+    if (allow_alt_ref &&
         (i >= MIN_GF_INTERVAL) &&
-        (i <= (cpi->frames_to_key - MIN_GF_INTERVAL)) &&          // dont use ARF very near next kf
+        // dont use ARF very near next kf
+        (i <= (cpi->frames_to_key - MIN_GF_INTERVAL)) &&
         (((next_frame.pcnt_inter > 0.75) &&
           ((mv_in_out_accumulator / (double)i > -0.2) || (mv_in_out_accumulator > -2.0)) &&
           //(cpi->gfu_boost>150) &&
@@ -2451,7 +2527,7 @@
     {
         double r;
         double motion_decay;
-        double motion_pct = next_frame.pcnt_motion;
+        double motion_pct;
 
         if (EOF == vp8_input_stats(cpi, &next_frame))
             break;
@@ -2471,6 +2547,7 @@
         loop_decay_rate = next_frame.pcnt_inter;
 
         // High % motion -> somewhat higher decay rate
+        motion_pct = next_frame.pcnt_motion;
         motion_decay = (1.0 - (motion_pct / 20.0));
         if (motion_decay < loop_decay_rate)
             loop_decay_rate = motion_decay;
diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c
index 77fbb29..9007853 100644
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -3853,7 +3853,7 @@
             // One pass more conservative
             else
                cpi->active_best_quality = kf_high_motion_minq[Q];
-         }
+        }
 
         else if (cm->refresh_golden_frame || cpi->common.refresh_alt_ref_frame)
         {
@@ -4188,7 +4188,7 @@
                                          IF_RTCD(&cpi->rtcd.variance));
 
             // The key frame is not good enough
-            if ( kf_err > ((cpi->ambient_err * 3) >> 2) )
+            if ( kf_err > ((cpi->ambient_err * 7) >> 3) )
             {
                 // Lower q_high
                 q_high = (Q > q_low) ? (Q - 1) : q_low;