shithub: libvpx

Download patch

ref: 1258cf62aeb8846f0f319d1149cd69a5c517c7ba
parent: cfe3f9173f7b19f41c59baf2390b6db65b023c00
author: Frank Galligan <fgalligan@google.com>
date: Wed Oct 6 08:51:00 EDT 2010

Fixed the timebase parameter of ivfenc.

Ivfenc will use timebase if it is set. If it is not set ivfenc will
still double the timebase so altref frames will have a unique pts.
Patch Set #3: Use integer math to generate source pts. Added a
framerate parameter. Increased the default timebase to milliseconds to
remove the *2 everywhere.

Change-Id: I8d25b5b2cb26deef7eb72d74b5f76c98cafaf4db

--- a/ivfenc.c
+++ b/ivfenc.c
@@ -423,10 +423,12 @@
         "Show encoder parameters");
 static const arg_def_t psnrarg          = ARG_DEF(NULL, "psnr", 0,
         "Show PSNR in status line");
+static const arg_def_t framerate        = ARG_DEF(NULL, "framerate", 1,
+        "Stream frame rate (rate/scale)");
 static const arg_def_t *main_args[] =
 {
     &codecarg, &passes, &pass_arg, &fpf_name, &limit, &deadline, &best_dl, &good_dl, &rt_dl,
-    &verbosearg, &psnrarg,
+    &verbosearg, &psnrarg, &framerate,
     NULL
 };
 
@@ -450,7 +452,7 @@
 static const arg_def_t *global_args[] =
 {
     &use_yv12, &use_i420, &usage, &threads, &profile,
-    &width, &height, &timebase, &error_resilient,
+    &width, &height, &timebase, &framerate, &error_resilient,
     &lag_in_frames, NULL
 };
 
@@ -614,10 +616,11 @@
     static const int        *ctrl_args_map = NULL;
     int                      verbose = 0, show_psnr = 0;
     int                      arg_use_i420 = 1;
-    int                      arg_have_timebase = 0;
     unsigned long            cx_time = 0;
     unsigned int             file_type, fourcc;
     y4m_input                y4m;
+    struct vpx_rational      arg_framerate = {30, 1};
+    int                      arg_have_framerate = 0;
 
     exec_name = argv_[0];
 
@@ -689,6 +692,11 @@
             arg_limit = arg_parse_uint(&arg);
         else if (arg_match(&arg, &psnrarg, argi))
             show_psnr = 1;
+        else if (arg_match(&arg, &framerate, argi))
+        {
+            arg_framerate = arg_parse_rational(&arg);
+            arg_have_framerate = 1;
+        }
         else
             argj++;
     }
@@ -720,6 +728,11 @@
         return EXIT_FAILURE;
     }
 
+    /* Change the default timebase to a high enough value so that the encoder
+     * will always create strictly increasing timestamps.
+     */
+    cfg.g_timebase.den = 1000;
+
     /* Now parse the remainder of the parameters. */
     for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step)
     {
@@ -735,10 +748,7 @@
         else if (arg_match(&arg, &height, argi))
             cfg.g_h = arg_parse_uint(&arg);
         else if (arg_match(&arg, &timebase, argi))
-        {
             cfg.g_timebase = arg_parse_rational(&arg);
-            arg_have_timebase = 1;
-        }
         else if (arg_match(&arg, &error_resilient, argi))
             cfg.g_error_resilient = arg_parse_uint(&arg);
         else if (arg_match(&arg, &lag_in_frames, argi))
@@ -883,16 +893,16 @@
                 file_type = FILE_TYPE_Y4M;
                 cfg.g_w = y4m.pic_w;
                 cfg.g_h = y4m.pic_h;
+
                 /* Use the frame rate from the file only if none was specified
                  * on the command-line.
                  */
-                if (!arg_have_timebase)
+                if (!arg_have_framerate)
                 {
-                    cfg.g_timebase.num = y4m.fps_d;
-                    cfg.g_timebase.den = y4m.fps_n;
-                    /* And don't reset it in the second pass.*/
-                    arg_have_timebase = 1;
+                    arg_framerate.num = y4m.fps_n;
+                    arg_framerate.den = y4m.fps_d;
                 }
+
                 arg_use_i420 = 0;
             }
             else
@@ -972,13 +982,6 @@
             else
                 vpx_img_alloc(&raw, arg_use_i420 ? VPX_IMG_FMT_I420 : VPX_IMG_FMT_YV12,
                               cfg.g_w, cfg.g_h, 1);
-
-            // This was added so that ivfenc will create monotically increasing
-            // timestamps.  Since we create new timestamps for alt-reference frames
-            // we need to make room in the series of timestamps.  Since there can
-            // only be 1 alt-ref frame ( current bitstream) multiplying by 2
-            // gives us enough room.
-            cfg.g_timebase.den *= 2;
         }
 
         outfile = strcmp(out_fn, "-") ? fopen(out_fn, "wb") : stdout;
@@ -1047,6 +1050,7 @@
             vpx_codec_iter_t iter = NULL;
             const vpx_codec_cx_pkt_t *pkt;
             struct vpx_usec_timer timer;
+            int64_t frame_start;
 
             if (!arg_limit || frames_in < arg_limit)
             {
@@ -1065,10 +1069,12 @@
 
             vpx_usec_timer_start(&timer);
 
-            // since we halved our timebase we need to double the timestamps
-            // and duration we pass in.
-            vpx_codec_encode(&encoder, frame_avail ? &raw : NULL, (frames_in - 1) * 2,
-                             2, 0, arg_deadline);
+            frame_start = (cfg.g_timebase.den * (int64_t)(frames_in - 1)
+                          * 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,
+                             0, arg_deadline);
             vpx_usec_timer_mark(&timer);
             cx_time += vpx_usec_timer_elapsed(&timer);
             ctx_exit_on_error(&encoder, "Failed to encode frame");
@@ -1116,14 +1122,11 @@
             fflush(stdout);
         }
 
-        /* this bitrate calc is simplified and relies on the fact that this
-         * application uses 1/timebase for framerate.
-         */
         fprintf(stderr,
                "\rPass %d/%d frame %4d/%-4d %7ldB %7ldb/f %7"PRId64"b/s"
                " %7lu %s (%.2f fps)\033[K", pass + 1,
                arg_passes, frames_in, frames_out, nbytes, nbytes * 8 / frames_in,
-               nbytes * 8 *(int64_t)cfg.g_timebase.den/2/ cfg.g_timebase.num / frames_in,
+               nbytes * 8 *(int64_t)arg_framerate.num / arg_framerate.den / frames_in,
                cx_time > 9999999 ? cx_time / 1000 : cx_time,
                cx_time > 9999999 ? "ms" : "us",
                (float)frames_in * 1000000.0 / (float)cx_time);