Add rc_max_intra_bitrate_pct control
authorJohn Koleszar <jkoleszar@google.com>
Mon, 25 Apr 2011 15:44:50 +0000 (11:44 -0400)
committerJohn Koleszar <jkoleszar@google.com>
Mon, 25 Apr 2011 17:47:14 +0000 (13:47 -0400)
Adds a control to limit the maximum size of a keyframe, as a function of
the per-frame bitrate. See this thread[1] for more detailed discussion:

[1]: http://groups.google.com/a/webmproject.org/group/codec-devel/browse_thread/thread/271b944a5e47ca38

Change-Id: I7337707642eb8041d1e593efc2edfdf66db02a94

vp8/common/onyx.h
vp8/encoder/onyx_if.c
vp8/vp8_cx_iface.c
vpx/vpx_encoder.h
vpxenc.c

index 426b8fc..c586d0d 100644 (file)
@@ -109,6 +109,7 @@ extern "C"
         int noise_sensitivity;   // parameter used for applying pre processing blur: recommendation 0
         int Sharpness;          // parameter used for sharpening output: recommendation 0:
         int cpu_used;
+        unsigned int rc_max_intra_bitrate_pct;
 
         // mode ->
         //(0)=Realtime/Live Encoding. This mode is optimized for realtim encoding (for example, capturing
index 7461edc..cbaab5f 100644 (file)
@@ -2704,6 +2704,19 @@ static int pick_frame_size(VP8_COMP *cpi)
         }
     }
 
+    /* Apply limits on keyframe target.
+     *
+     * TODO: move this after consolidating
+     * vp8_calc_iframe_target_size() and vp8_calc_auto_iframe_target_size()
+     */
+    if (cm->frame_type == KEY_FRAME && cpi->oxcf.rc_max_intra_bitrate_pct)
+    {
+        unsigned int max_rate = cpi->av_per_frame_bandwidth
+                                * cpi->oxcf.rc_max_intra_bitrate_pct / 100;
+
+        if (cpi->this_frame_target > max_rate)
+            cpi->this_frame_target = max_rate;
+    }
     return 1;
 }
 
index 973265c..17eb6a2 100644 (file)
@@ -304,6 +304,7 @@ static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
     }
 
     oxcf->target_bandwidth       = cfg.rc_target_bitrate;
+    oxcf->rc_max_intra_bitrate_pct = cfg.rc_max_intra_bitrate_pct;
 
     oxcf->best_allowed_q          = cfg.rc_min_quantizer;
     oxcf->worst_allowed_q         = cfg.rc_max_quantizer;
@@ -1083,7 +1084,7 @@ static vpx_codec_enc_cfg_map_t vp8e_usage_cfg_map[] =
         {0},                /* rc_twopass_stats_in */
 #endif
         256,                /* rc_target_bandwidth */
-
+        0,                  /* rc_max_intra_bitrate_pct */
         4,                  /* rc_min_quantizer */
         63,                 /* rc_max_quantizer */
         95,                 /* rc_undershoot_pct */
index 9c44414..225d345 100644 (file)
@@ -398,6 +398,21 @@ extern "C" {
         unsigned int           rc_target_bitrate;
 
 
+        /*!\brief Max data rate for Intra frames
+         *
+         * This value controls additional clamping on the maximum size of a
+         * keyframe. It is expressed as a percentage of the average
+         * per-frame bitrate, with the special (and default) value 0 meaning
+         * unlimited, or no additional clamping beyond the codec's built-in
+         * algorithm.
+         *
+         * For example, to allocate no more than 4.5 frames worth of bitrate
+         * to a keyframe, set this to 450.
+         *
+         */
+        unsigned int           rc_max_intra_bitrate_pct;
+
+
         /*
          * quantizer settings
          */
index 39256b6..4c43a6e 100644 (file)
--- a/vpxenc.c
+++ b/vpxenc.c
@@ -962,11 +962,14 @@ static const arg_def_t buf_initial_sz     = ARG_DEF(NULL, "buf-initial-sz", 1,
         "Client initial buffer size (ms)");
 static const arg_def_t buf_optimal_sz     = ARG_DEF(NULL, "buf-optimal-sz", 1,
         "Client optimal buffer size (ms)");
+static const arg_def_t max_intra_rate_pct = ARG_DEF(NULL, "max-intra-rate", 1,
+        "Max I-frame bitrate (pct)");
 static const arg_def_t *rc_args[] =
 {
     &dropframe_thresh, &resize_allowed, &resize_up_thresh, &resize_down_thresh,
     &end_usage, &target_bitrate, &min_quantizer, &max_quantizer,
     &undershoot_pct, &overshoot_pct, &buf_sz, &buf_initial_sz, &buf_optimal_sz,
+    &max_intra_rate_pct,
     NULL
 };
 
@@ -1279,6 +1282,8 @@ int main(int argc, const char **argv_)
             cfg.rc_end_usage = arg_parse_enum_or_int(&arg);
         else if (arg_match(&arg, &target_bitrate, argi))
             cfg.rc_target_bitrate = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &max_intra_rate_pct, argi))
+            cfg.rc_max_intra_bitrate_pct = arg_parse_uint(&arg);
         else if (arg_match(&arg, &min_quantizer, argi))
             cfg.rc_min_quantizer = arg_parse_uint(&arg);
         else if (arg_match(&arg, &max_quantizer, argi))