Merge "Add a conservative RD based active map in vp9."
diff --git a/examples.mk b/examples.mk
index 5c6e42d..7ec1a8e 100644
--- a/examples.mk
+++ b/examples.mk
@@ -140,13 +140,13 @@
 endif
 decode_with_partial_drops.GUID           = 61C2D026-5754-46AC-916F-1343ECC5537E
 decode_with_partial_drops.DESCRIPTION    = Drops parts of frames while decoding
-EXAMPLES-$(CONFIG_VP8_ENCODER)     += vp8_set_maps.c
-vp8_set_maps.SRCS                  += ivfenc.h ivfenc.c
-vp8_set_maps.SRCS                  += tools_common.h tools_common.c
-vp8_set_maps.SRCS                  += video_common.h
-vp8_set_maps.SRCS                  += video_writer.h video_writer.c
-vp8_set_maps.GUID                   = ECB2D24D-98B8-4015-A465-A4AF3DCC145F
-vp8_set_maps.DESCRIPTION            = VP8 set active and ROI maps
+EXAMPLES-$(CONFIG_ENCODERS)        += set_maps.c
+set_maps.SRCS                      += ivfenc.h ivfenc.c
+set_maps.SRCS                      += tools_common.h tools_common.c
+set_maps.SRCS                      += video_common.h
+set_maps.SRCS                      += video_writer.h video_writer.c
+set_maps.GUID                       = ECB2D24D-98B8-4015-A465-A4AF3DCC145F
+set_maps.DESCRIPTION                = Set active and ROI maps
 EXAMPLES-$(CONFIG_VP8_ENCODER)     += vp8cx_set_ref.c
 vp8cx_set_ref.SRCS                 += ivfenc.h ivfenc.c
 vp8cx_set_ref.SRCS                 += tools_common.h tools_common.c
diff --git a/examples/vp8_set_maps.c b/examples/set_maps.c
similarity index 87%
rename from examples/vp8_set_maps.c
rename to examples/set_maps.c
index f3cc9a7..4343832 100644
--- a/examples/vp8_set_maps.c
+++ b/examples/set_maps.c
@@ -56,7 +56,8 @@
 static const char *exec_name;
 
 void usage_exit() {
-  fprintf(stderr, "Usage: %s <width> <height> <infile> <outfile>\n", exec_name);
+  fprintf(stderr, "Usage: %s <codec> <width> <height> <infile> <outfile>\n",
+          exec_name);
   exit(EXIT_FAILURE);
 }
 
@@ -65,8 +66,8 @@
   unsigned int i;
   vpx_roi_map_t roi = {0};
 
-  roi.rows = cfg->g_h / 16;
-  roi.cols = cfg->g_w / 16;
+  roi.rows = (cfg->g_h + 15) / 16;
+  roi.cols = (cfg->g_w + 15) / 16;
 
   roi.delta_q[0] = 0;
   roi.delta_q[1] = -2;
@@ -98,8 +99,8 @@
   unsigned int i;
   vpx_active_map_t map = {0};
 
-  map.rows = cfg->g_h / 16;
-  map.cols = cfg->g_w / 16;
+  map.rows = (cfg->g_h + 15) / 16;
+  map.cols = (cfg->g_w + 15) / 16;
 
   map.active_map = (uint8_t *)malloc(map.rows * map.cols);
   for (i = 0; i < map.rows * map.cols; ++i)
@@ -115,8 +116,8 @@
                              vpx_codec_ctx_t *codec) {
   vpx_active_map_t map = {0};
 
-  map.rows = cfg->g_h / 16;
-  map.cols = cfg->g_w / 16;
+  map.rows = (cfg->g_h + 15) / 16;
+  map.cols = (cfg->g_w + 15) / 16;
   map.active_map = NULL;
 
   if (vpx_codec_control(codec, VP8E_SET_ACTIVEMAP, &map))
@@ -161,20 +162,20 @@
   VpxVideoWriter *writer = NULL;
   const VpxInterface *encoder = NULL;
   const int fps = 2;        // TODO(dkovalev) add command line argument
-  const int bitrate = 200;   // kbit/s TODO(dkovalev) add command line argument
+  const double bits_per_pixel_per_frame = 0.067;
 
   exec_name = argv[0];
 
-  if (argc != 5)
+  if (argc != 6)
     die("Invalid number of arguments");
 
-  encoder = get_vpx_encoder_by_name("vp8");  // only vp8 for now
+  encoder = get_vpx_encoder_by_name(argv[1]);
   if (!encoder)
     die("Unsupported codec.");
 
   info.codec_fourcc = encoder->fourcc;
-  info.frame_width = strtol(argv[1], NULL, 0);
-  info.frame_height = strtol(argv[2], NULL, 0);
+  info.frame_width = strtol(argv[2], NULL, 0);
+  info.frame_height = strtol(argv[3], NULL, 0);
   info.time_base.numerator = 1;
   info.time_base.denominator = fps;
 
@@ -200,14 +201,16 @@
   cfg.g_h = info.frame_height;
   cfg.g_timebase.num = info.time_base.numerator;
   cfg.g_timebase.den = info.time_base.denominator;
-  cfg.rc_target_bitrate = bitrate;
+  cfg.rc_target_bitrate = (unsigned int)(bits_per_pixel_per_frame * cfg.g_w *
+                                         cfg.g_h * fps / 1000);
+  cfg.g_lag_in_frames = 0;
 
-  writer = vpx_video_writer_open(argv[4], kContainerIVF, &info);
+  writer = vpx_video_writer_open(argv[5], kContainerIVF, &info);
   if (!writer)
-    die("Failed to open %s for writing.", argv[4]);
+    die("Failed to open %s for writing.", argv[5]);
 
-  if (!(infile = fopen(argv[3], "rb")))
-    die("Failed to open %s for reading.", argv[3]);
+  if (!(infile = fopen(argv[4], "rb")))
+    die("Failed to open %s for reading.", argv[4]);
 
   if (vpx_codec_enc_init(&codec, encoder->interface(), &cfg, 0))
     die_codec(&codec, "Failed to initialize encoder");
@@ -215,7 +218,7 @@
   while (vpx_img_read(&raw, infile)) {
     ++frame_count;
 
-    if (frame_count == 22) {
+    if (frame_count == 22 && encoder->fourcc == VP8_FOURCC) {
       set_roi_map(&cfg, &codec);
     } else if (frame_count == 33) {
       set_active_map(&cfg, &codec);
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index a52171c..9cc43f9 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -2284,7 +2284,7 @@
     if (cpi->sf.tx_size_search_method == USE_LARGESTALL) {
       return ALLOW_32X32;
     } else if (cpi->sf.tx_size_search_method == USE_FULL_RD) {
-      const int frame_type = get_frame_type(cpi);
+      const MV_REFERENCE_FRAME frame_type = get_frame_type(cpi);
       return cpi->rd_tx_select_threshes[frame_type][ALLOW_32X32] >
                  cpi->rd_tx_select_threshes[frame_type][TX_MODE_SELECT] ?
                      ALLOW_32X32 : TX_MODE_SELECT;
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index f548de5..acb5a09 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -1412,7 +1412,7 @@
     active_max_gf_interval = rc->max_gf_interval;
 
   i = 0;
-  while (i < twopass->static_scene_max_gf_interval && i < rc->frames_to_key) {
+  while (i < rc->static_scene_max_gf_interval && i < rc->frames_to_key) {
     ++i;
 
     // Accumulate error score of frames in this gf group.
diff --git a/vp9/encoder/vp9_firstpass.h b/vp9/encoder/vp9_firstpass.h
index 9f44a30..278b22c 100644
--- a/vp9/encoder/vp9_firstpass.h
+++ b/vp9/encoder/vp9_firstpass.h
@@ -57,7 +57,6 @@
   double modified_error_left;
   double kf_intra_err_min;
   double gf_intra_err_min;
-  int static_scene_max_gf_interval;
   int kf_bits;
   // Remaining error from uncoded frames in a gf group. Two pass use only
   int64_t gf_group_error_left;
diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c
index 57d2c78..0a5033f 100644
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -97,7 +97,7 @@
 static const double in_frame_q_adj_ratio[MAX_SEGMENTS] =
   {1.0, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0};
 
-static INLINE void Scale2Ratio(int mode, int *hr, int *hs) {
+static INLINE void Scale2Ratio(VPX_SCALING mode, int *hr, int *hs) {
   switch (mode) {
     case NORMAL:
       *hr = 1;
@@ -707,7 +707,6 @@
   if (speed >= 5) {
     sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
     sf->partition_search_type = FIXED_PARTITION;
-    sf->always_this_block_size = BLOCK_16X16;
     sf->tx_size_search_method = frame_is_intra_only(cm) ?
       USE_FULL_RD : USE_LARGESTALL;
     sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH |
@@ -943,6 +942,9 @@
   for (i = 0; i < BLOCK_SIZES; ++i)
     sf->disable_inter_mode_mask[i] = 0;
   sf->max_intra_bsize = BLOCK_64X64;
+  // This setting only takes effect when partition_search_type is set
+  // to FIXED_PARTITION.
+  sf->always_this_block_size = BLOCK_16X16;
 
   switch (cpi->oxcf.mode) {
     case MODE_BESTQUALITY:
@@ -1134,21 +1136,19 @@
 
 void vp9_new_framerate(VP9_COMP *cpi, double framerate) {
   VP9_COMMON *const cm = &cpi->common;
+  RATE_CONTROL *const rc = &cpi->rc;
+  VP9_CONFIG *const oxcf = &cpi->oxcf;
   int vbr_max_bits;
 
-  if (framerate < 0.1)
-    framerate = 30;
-
-  cpi->oxcf.framerate = framerate;
+  oxcf->framerate = framerate < 0.1 ? 30 : framerate;
   cpi->output_framerate = cpi->oxcf.framerate;
-  cpi->rc.av_per_frame_bandwidth = (int)(cpi->oxcf.target_bandwidth
-                                         / cpi->output_framerate);
-  cpi->rc.min_frame_bandwidth = (int)(cpi->rc.av_per_frame_bandwidth *
-                                      cpi->oxcf.two_pass_vbrmin_section / 100);
+  rc->av_per_frame_bandwidth = (int)(oxcf->target_bandwidth /
+                                         cpi->output_framerate);
+  rc->min_frame_bandwidth = (int)(rc->av_per_frame_bandwidth *
+                                      oxcf->two_pass_vbrmin_section / 100);
 
 
-  cpi->rc.min_frame_bandwidth = MAX(cpi->rc.min_frame_bandwidth,
-                                    FRAME_OVERHEAD_BITS);
+  rc->min_frame_bandwidth = MAX(rc->min_frame_bandwidth, FRAME_OVERHEAD_BITS);
 
   // A maximum bitrate for a frame is defined.
   // The baseline for this aligns with HW implementations that
@@ -1158,28 +1158,28 @@
   // be acheived because of a user specificed max q (e.g. when the user
   // specifies lossless encode.
   //
-  vbr_max_bits = (int)(((int64_t)cpi->rc.av_per_frame_bandwidth *
-      cpi->oxcf.two_pass_vbrmax_section) / 100);
-  cpi->rc.max_frame_bandwidth =
-      MAX(MAX((cm->MBs * MAX_MB_RATE), MAXRATE_1080P), vbr_max_bits);
+  vbr_max_bits = (int)(((int64_t)rc->av_per_frame_bandwidth *
+      oxcf->two_pass_vbrmax_section) / 100);
+  rc->max_frame_bandwidth = MAX(MAX((cm->MBs * MAX_MB_RATE), MAXRATE_1080P),
+                                vbr_max_bits);
 
   // Set Maximum gf/arf interval
-  cpi->rc.max_gf_interval = 16;
+  rc->max_gf_interval = 16;
 
   // Extended interval for genuinely static scenes
-  cpi->twopass.static_scene_max_gf_interval = cpi->key_frame_frequency >> 1;
+  rc->static_scene_max_gf_interval = cpi->key_frame_frequency >> 1;
 
   // Special conditions when alt ref frame enabled in lagged compress mode
-  if (cpi->oxcf.play_alternate && cpi->oxcf.lag_in_frames) {
-    if (cpi->rc.max_gf_interval > cpi->oxcf.lag_in_frames - 1)
-      cpi->rc.max_gf_interval = cpi->oxcf.lag_in_frames - 1;
+  if (oxcf->play_alternate && oxcf->lag_in_frames) {
+    if (rc->max_gf_interval > oxcf->lag_in_frames - 1)
+      rc->max_gf_interval = oxcf->lag_in_frames - 1;
 
-    if (cpi->twopass.static_scene_max_gf_interval > cpi->oxcf.lag_in_frames - 1)
-      cpi->twopass.static_scene_max_gf_interval = cpi->oxcf.lag_in_frames - 1;
+    if (rc->static_scene_max_gf_interval > oxcf->lag_in_frames - 1)
+      rc->static_scene_max_gf_interval = oxcf->lag_in_frames - 1;
   }
 
-  if (cpi->rc.max_gf_interval > cpi->twopass.static_scene_max_gf_interval)
-    cpi->rc.max_gf_interval = cpi->twopass.static_scene_max_gf_interval;
+  if (rc->max_gf_interval > rc->static_scene_max_gf_interval)
+    rc->max_gf_interval = rc->static_scene_max_gf_interval;
 }
 
 static int64_t rescale(int64_t val, int64_t num, int denom) {
@@ -1410,6 +1410,10 @@
       cpi->oxcf.cpu_used = clamp(cpi->oxcf.cpu_used, -5, 5);
       break;
 
+    case MODE_BESTQUALITY:
+      cpi->pass = 0;
+      break;
+
     case MODE_FIRSTPASS:
       cpi->pass = 1;
       break;
diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h
index 1540d6e..8c6b48c 100644
--- a/vp9/encoder/vp9_onyx_int.h
+++ b/vp9/encoder/vp9_onyx_int.h
@@ -442,8 +442,6 @@
   int avg_frame_size;
 } LAYER_CONTEXT;
 
-#define MAX_SEGMENTS 8
-
 typedef enum {
   NORMAL      = 0,
   FOURFIVE    = 1,
@@ -522,7 +520,7 @@
   //     were generated in the first encoding pass to create the compressed
   //     output using the highest possible quality, and taking a
   //    longer amount of time to encode.. ( speed setting ignored )
-  int mode;
+  MODE mode;
 
   // Key Framing Operations
   int auto_key;  // autodetect cut scenes and set the keyframes
@@ -533,7 +531,7 @@
   // ----------------------------------------------------------------
   // DATARATE CONTROL OPTIONS
 
-  int end_usage;  // vbr or cbr
+  END_USAGE end_usage;  // vbr or cbr
 
   // buffer targeting aggressiveness
   int under_shoot_pct;
@@ -682,13 +680,13 @@
   int rd_thresh_freq_sub8x8[BLOCK_SIZES][MAX_REFS];
 
   int64_t rd_comp_pred_diff[REFERENCE_MODES];
-  int64_t rd_prediction_type_threshes[4][REFERENCE_MODES];
+  int64_t rd_prediction_type_threshes[MAX_REF_FRAMES][REFERENCE_MODES];
   int64_t rd_tx_select_diff[TX_MODES];
   // FIXME(rbultje) can this overflow?
-  int rd_tx_select_threshes[4][TX_MODES];
+  int rd_tx_select_threshes[MAX_REF_FRAMES][TX_MODES];
 
   int64_t rd_filter_diff[SWITCHABLE_FILTER_CONTEXTS];
-  int64_t rd_filter_threshes[4][SWITCHABLE_FILTER_CONTEXTS];
+  int64_t rd_filter_threshes[MAX_REF_FRAMES][SWITCHABLE_FILTER_CONTEXTS];
   int64_t rd_filter_cache[SWITCHABLE_FILTER_CONTEXTS];
   int64_t mask_filter_rd;
 
diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h
index 5dbc7d1..a6f2c31 100644
--- a/vp9/encoder/vp9_ratectrl.h
+++ b/vp9/encoder/vp9_ratectrl.h
@@ -37,6 +37,7 @@
   int frames_since_golden;
   int frames_till_gf_update_due;
   int max_gf_interval;
+  int static_scene_max_gf_interval;
   int baseline_gf_interval;
   int frames_to_key;
   int frames_since_key;
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index db07927..e957b15 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -3720,16 +3720,13 @@
   // combination that wins out.
   if (cpi->sf.adaptive_rd_thresh) {
     for (mode_index = 0; mode_index < MAX_MODES; ++mode_index) {
+      int *const fact = &cpi->rd_thresh_freq_fact[bsize][mode_index];
+
       if (mode_index == best_mode_index) {
-        cpi->rd_thresh_freq_fact[bsize][mode_index] -=
-          (cpi->rd_thresh_freq_fact[bsize][mode_index] >> 3);
+        *fact -= (*fact >> 3);
       } else {
-        cpi->rd_thresh_freq_fact[bsize][mode_index] += RD_THRESH_INC;
-        if (cpi->rd_thresh_freq_fact[bsize][mode_index] >
-            (cpi->sf.adaptive_rd_thresh * RD_THRESH_MAX_FACT)) {
-          cpi->rd_thresh_freq_fact[bsize][mode_index] =
-            cpi->sf.adaptive_rd_thresh * RD_THRESH_MAX_FACT;
-        }
+        *fact = MIN(*fact + RD_THRESH_INC,
+                    cpi->sf.adaptive_rd_thresh * RD_THRESH_MAX_FACT);
       }
     }
   }
@@ -4445,16 +4442,13 @@
   // combination that wins out.
   if (cpi->sf.adaptive_rd_thresh) {
     for (mode_index = 0; mode_index < MAX_REFS; ++mode_index) {
+      int *const fact = &cpi->rd_thresh_freq_sub8x8[bsize][mode_index];
+
       if (mode_index == best_mode_index) {
-        cpi->rd_thresh_freq_sub8x8[bsize][mode_index] -=
-          (cpi->rd_thresh_freq_sub8x8[bsize][mode_index] >> 3);
+        *fact -= (*fact >> 3);
       } else {
-        cpi->rd_thresh_freq_sub8x8[bsize][mode_index] += RD_THRESH_INC;
-        if (cpi->rd_thresh_freq_sub8x8[bsize][mode_index] >
-            (cpi->sf.adaptive_rd_thresh * RD_THRESH_MAX_FACT)) {
-          cpi->rd_thresh_freq_sub8x8[bsize][mode_index] =
-            cpi->sf.adaptive_rd_thresh * RD_THRESH_MAX_FACT;
-        }
+        *fact = MIN(*fact + RD_THRESH_INC,
+                    cpi->sf.adaptive_rd_thresh * RD_THRESH_MAX_FACT);
       }
     }
   }
diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c
index 5ba8cdc..a20209f 100644
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -577,33 +577,27 @@
 }
 
 static void pick_quickcompress_mode(vpx_codec_alg_priv_t  *ctx,
-                                    unsigned long          duration,
-                                    unsigned long          deadline) {
-  unsigned int new_qc;
-
-  /* Use best quality mode if no deadline is given. */
-  new_qc = MODE_BESTQUALITY;
+                                    unsigned long duration,
+                                    unsigned long deadline) {
+  // Use best quality mode if no deadline is given.
+  MODE new_qc = MODE_BESTQUALITY;
 
   if (deadline) {
-      uint64_t     duration_us;
+    // Convert duration parameter from stream timebase to microseconds
+    const uint64_t duration_us = (uint64_t)duration * 1000000 *
+                               (uint64_t)ctx->cfg.g_timebase.num /
+                               (uint64_t)ctx->cfg.g_timebase.den;
 
-      /* Convert duration parameter from stream timebase to microseconds */
-      duration_us = (uint64_t)duration * 1000000
-                    * (uint64_t)ctx->cfg.g_timebase.num
-                    / (uint64_t)ctx->cfg.g_timebase.den;
-
-      /* If the deadline is more that the duration this frame is to be shown,
-       * use good quality mode. Otherwise use realtime mode.
-       */
-      new_qc = (deadline > duration_us) ? MODE_GOODQUALITY : MODE_REALTIME;
+    // If the deadline is more that the duration this frame is to be shown,
+    // use good quality mode. Otherwise use realtime mode.
+    new_qc = (deadline > duration_us) ? MODE_GOODQUALITY : MODE_REALTIME;
   }
 
   if (ctx->cfg.g_pass == VPX_RC_FIRST_PASS)
     new_qc = MODE_FIRSTPASS;
   else if (ctx->cfg.g_pass == VPX_RC_LAST_PASS)
-    new_qc = (new_qc == MODE_BESTQUALITY)
-             ? MODE_SECONDPASS_BEST
-             : MODE_SECONDPASS;
+    new_qc = (new_qc == MODE_BESTQUALITY) ? MODE_SECONDPASS_BEST
+                                          : MODE_SECONDPASS;
 
   if (ctx->oxcf.mode != new_qc) {
     ctx->oxcf.mode = new_qc;