shithub: libvpx

Download patch

ref: f7e187d3626f029490b8b619fb80da1b0e77dcfe
parent: bd05d9e480623536e35b76cf3cfd6b8884d254ba
author: John Koleszar <jkoleszar@google.com>
date: Thu Nov 4 11:05:45 EDT 2010

improve average framerate calculation

Change Ice204e86 identified a problem with bitrate undershoot due to
low precision in the timestamps passed to the library. This patch
takes a different approach by calculating the duration of this frame
and passing it to the library, rather than using a fixed duration
and letting the library average it out with higher precision
timestamps. This part of the fix only applies to vpxenc.

This patch also attempts to fix the problem for generic applications
that may have made the same mistake vpxenc did. Instead of
calculating this frame's duration by the difference of this frame's
and the last frame's start time, we use the end times instead. This
allows the framerate calculation to scavenge "unclaimed" time from
the last frame. For instance:

  start |  end  | calculated duration
  ======+=======+====================
    0ms    33ms   33ms
   33ms    66ms   33ms
   66ms    99ms   33ms
  100ms   133ms   34ms

Change-Id: I92be4b3518e0bd530e97f90e69e75330a4c413fc

--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -4972,17 +4972,16 @@
 
     *frame_flags = cpi->source_frame_flags;
 
-#if CONFIG_PSNR
-
     if (cpi->source_time_stamp < cpi->first_time_stamp_ever)
+    {
         cpi->first_time_stamp_ever = cpi->source_time_stamp;
+        cpi->last_end_time_stamp_seen = cpi->source_time_stamp;
+    }
 
-#endif
-
     // adjust frame rates based on timestamps given
     if (!cm->refresh_alt_ref_frame)
     {
-        if (cpi->last_time_stamp_seen == 0)
+        if (cpi->source_time_stamp == cpi->first_time_stamp_ever)
         {
             double this_fps = 10000000.000 / (cpi->source_end_time_stamp - cpi->source_time_stamp);
 
@@ -4990,7 +4989,8 @@
         }
         else
         {
-            long long nanosecs = cpi->source_time_stamp - cpi->last_time_stamp_seen;
+            long long nanosecs = cpi->source_end_time_stamp
+                - cpi->last_end_time_stamp_seen;
             double this_fps = 10000000.000 / nanosecs;
 
             vp8_new_frame_rate(cpi, (7 * cpi->oxcf.frame_rate + this_fps) / 8);
@@ -4998,6 +4998,7 @@
         }
 
         cpi->last_time_stamp_seen = cpi->source_time_stamp;
+        cpi->last_end_time_stamp_seen = cpi->source_end_time_stamp;
     }
 
     if (cpi->compressor_speed == 2)
--- a/vp8/encoder/onyx_int.h
+++ b/vp8/encoder/onyx_int.h
@@ -399,6 +399,7 @@
     int inter_frame_target;
     double output_frame_rate;
     long long last_time_stamp_seen;
+    long long last_end_time_stamp_seen;
     long long first_time_stamp_ever;
 
     int ni_av_qi;
--- a/vpxenc.c
+++ b/vpxenc.c
@@ -1188,7 +1188,7 @@
     /* Change the default timebase to a high enough value so that the encoder
      * will always create strictly increasing timestamps.
      */
-    cfg.g_timebase.den = 100000;
+    cfg.g_timebase.den = 1000;
 
     /* Never use the library's default resolution, require it be parsed
      * from the file or set on the command line.
@@ -1544,7 +1544,7 @@
             vpx_codec_iter_t iter = NULL;
             const vpx_codec_cx_pkt_t *pkt;
             struct vpx_usec_timer timer;
-            int64_t frame_start;
+            int64_t frame_start, next_frame_start;
 
             if (!arg_limit || frames_in < arg_limit)
             {
@@ -1565,9 +1565,11 @@
 
             frame_start = (cfg.g_timebase.den * (int64_t)(frames_in - 1)
                           * arg_framerate.den) / cfg.g_timebase.num / arg_framerate.num;
+            next_frame_start = (cfg.g_timebase.den * (int64_t)(frames_in)
+                                * arg_framerate.den)
+                                / cfg.g_timebase.num / arg_framerate.num;
             vpx_codec_encode(&encoder, frame_avail ? &raw : NULL, frame_start,
-                             cfg.g_timebase.den * arg_framerate.den
-                             / cfg.g_timebase.num / arg_framerate.num,
+                             next_frame_start - frame_start,
                              0, arg_deadline);
             vpx_usec_timer_mark(&timer);
             cx_time += vpx_usec_timer_elapsed(&timer);
--