shithub: libvpx

Download patch

ref: 18c902f8a416ae97de8143840234a416700a1e64
parent: 0e78efad0be73d293880d1b71053c0d70a50a080
parent: c239a1b67c9c5ff25a04ba89eca45245b1e615a2
author: Paul Wilkins <paulwilkins@google.com>
date: Tue Aug 31 22:45:12 EDT 2010

Merge "Improved Force Key Frame Behaviour"

--- a/vp8/encoder/firstpass.c
+++ b/vp8/encoder/firstpass.c
@@ -2095,26 +2095,26 @@
         kf_group_intra_err += this_frame->intra_error;
         kf_group_coded_err += this_frame->coded_error;
 
+        // load a the next frame's stats
         vpx_memcpy(&last_frame, this_frame, sizeof(*this_frame));
+        vp8_input_stats(cpi, this_frame);
 
         // Provided that we are not at the end of the file...
-        if (EOF != vp8_input_stats(cpi, this_frame))
+        if (cpi->oxcf.auto_key
+            && lookup_next_frame_stats(cpi, &next_frame) != EOF)
         {
-            if (lookup_next_frame_stats(cpi, &next_frame) != EOF)
-            {
-                if (test_candidate_kf(cpi, &last_frame, this_frame, &next_frame))
-                    break;
-            }
-        }
+            if (test_candidate_kf(cpi, &last_frame, this_frame, &next_frame))
+                break;
 
-        // Step on to the next frame
-        cpi->frames_to_key ++;
+            // Step on to the next frame
+            cpi->frames_to_key ++;
 
-        // If we don't have a real key frame within the next two
-        // forcekeyframeevery intervals then break out of the loop.
-        if (cpi->frames_to_key >= 2 *(int)cpi->key_frame_frequency)
-            break;
-
+            // If we don't have a real key frame within the next two
+            // forcekeyframeevery intervals then break out of the loop.
+            if (cpi->frames_to_key >= 2 *(int)cpi->key_frame_frequency)
+                break;
+        } else
+            cpi->frames_to_key ++;
     }
 
     // If there is a max kf interval set by the user we must obey it.
@@ -2121,7 +2121,8 @@
     // We already breakout of the loop above at 2x max.
     // This code centers the extra kf if the actual natural
     // interval is between 1x and 2x
-    if ( cpi->frames_to_key > (int)cpi->key_frame_frequency )
+    if (cpi->oxcf.auto_key
+        && cpi->frames_to_key > (int)cpi->key_frame_frequency )
     {
         cpi->frames_to_key /= 2;
 
@@ -2388,13 +2389,19 @@
                 cpi->kf_bits = (3 * cpi->buffer_level) >> 2;
         }
 
-        // If the key frame is actually easier than the average for the kf group (which does sometimes happen... eg a blank intro frame)
-        // Then use an alternate calculation based on the kf error score which should give a smaller key frame.
+        // If the key frame is actually easier than the average for the
+        // kf group (which does sometimes happen... eg a blank intro frame)
+        // Then use an alternate calculation based on the kf error score
+        // which should give a smaller key frame.
         if (kf_mod_err < kf_group_err / cpi->frames_to_key)
         {
-            double  alt_kf_grp_bits = ((double)cpi->bits_left * (kf_mod_err * (double)cpi->frames_to_key) / cpi->modified_total_error_left) ;
+            double  alt_kf_grp_bits =
+                        ((double)cpi->bits_left *
+                         (kf_mod_err * (double)cpi->frames_to_key) /
+                         DOUBLE_DIVIDE_CHECK(cpi->modified_total_error_left));
 
-            alt_kf_bits = (int)((double)kf_boost * (alt_kf_grp_bits / (double)allocation_chunks));
+            alt_kf_bits = (int)((double)kf_boost *
+                                (alt_kf_grp_bits / (double)allocation_chunks));
 
             if (cpi->kf_bits > alt_kf_bits)
             {
@@ -2401,10 +2408,15 @@
                 cpi->kf_bits = alt_kf_bits;
             }
         }
-        // Else if it is much harder than other frames in the group make sure it at least receives an allocation in keeping with its relative error score
+        // Else if it is much harder than other frames in the group make sure
+        // it at least receives an allocation in keeping with its relative
+        // error score
         else
         {
-            alt_kf_bits = (int)((double)cpi->bits_left * (kf_mod_err / cpi->modified_total_error_left));
+            alt_kf_bits =
+                (int)((double)cpi->bits_left *
+                      (kf_mod_err /
+                       DOUBLE_DIVIDE_CHECK(cpi->modified_total_error_left)));
 
             if (alt_kf_bits > cpi->kf_bits)
             {
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -2818,23 +2818,17 @@
         cm->frame_type = KEY_FRAME;
 
     }
-    // Auto key frames (Only two pass will enter here)
-    else if (cm->frame_type == KEY_FRAME)
+    // Special case for forced key frames
+    // The frame sizing here is still far from ideal for 2 pass.
+    else if (cm->frame_flags & FRAMEFLAGS_KEY)
     {
-        vp8_calc_auto_iframe_target_size(cpi);
-    }
-    // Forced key frames (by interval or an external signal)
-    else if ((cm->frame_flags & FRAMEFLAGS_KEY) ||
-             (cpi->oxcf.auto_key && (cpi->frames_since_key % cpi->key_frame_frequency == 0)))
-    {
-        // Key frame from VFW/auto-keyframe/first frame
         cm->frame_type = KEY_FRAME;
-
         resize_key_frame(cpi);
-
-        // Compute target frame size
-        if (cpi->pass != 2)
-            vp8_calc_iframe_target_size(cpi);
+        vp8_calc_iframe_target_size(cpi);
+    }
+    else if (cm->frame_type == KEY_FRAME)
+    {
+        vp8_calc_auto_iframe_target_size(cpi);
     }
     else
     {
--- a/vp8/encoder/ratectrl.c
+++ b/vp8/encoder/ratectrl.c
@@ -1444,6 +1444,9 @@
     }
     else
     {
+        int last_kf_interval =
+                (cpi->frames_since_key > 0) ? cpi->frames_since_key : 1;
+
         // reset keyframe context and calculate weighted average of last KEY_FRAME_CONTEXT keyframes
         for (i = 0; i < KEY_FRAME_CONTEXT; i++)
         {
@@ -1454,8 +1457,8 @@
             }
             else
             {
-                cpi->prior_key_frame_size[KEY_FRAME_CONTEXT - 1]     = cpi->projected_frame_size;
-                cpi->prior_key_frame_distance[KEY_FRAME_CONTEXT - 1] = cpi->frames_since_key;
+                cpi->prior_key_frame_size[i]     = cpi->projected_frame_size;
+                cpi->prior_key_frame_distance[i] = last_kf_interval;
             }
 
             av_key_frame_bits      += prior_key_frame_weight[i] * cpi->prior_key_frame_size[i];