shithub: libvpx

Download patch

ref: 356a7e96420c297d87fad5c00640ddc2ea0556c3
parent: 9453c6472630cf1485161ef7499e658f5c378ceb
parent: 507fd5220b50be735c462308778efed9709404a6
author: Yunqing Wang <yunqingwang@google.com>
date: Tue Feb 11 16:07:24 EST 2014

Merge "Enable encode_breakout in real time encoding"

--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -613,7 +613,7 @@
     x->encode_breakout = cpi->segment_encode_breakout[mbmi->segment_id];
   } else {
     mbmi->segment_id = 0;
-    x->encode_breakout = cpi->oxcf.encode_breakout;
+    x->encode_breakout = cpi->encode_breakout;
   }
 }
 
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -2328,11 +2328,11 @@
 
     if (twopass->gf_zeromotion_pct > 995) {
       // As long as max_thresh for encode breakout is small enough, it is ok
-      // to enable it for no-show frame, i.e. set enable_encode_breakout to 2.
+      // to enable it for show frame, i.e. set allow_encode_breakout to 2.
       if (!cm->show_frame)
-        cpi->enable_encode_breakout = 0;
+        cpi->allow_encode_breakout = ENCODE_BREAKOUT_DISABLED;
       else
-        cpi->enable_encode_breakout = 2;
+        cpi->allow_encode_breakout = ENCODE_BREAKOUT_LIMITED;
     }
 
     rc->frames_till_gf_update_due = rc->baseline_gf_interval;
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -744,6 +744,8 @@
   sf->static_segmentation = 0;
   sf->adaptive_rd_thresh = 1;
   sf->recode_loop = ((speed < 1) ? ALLOW_RECODE : ALLOW_RECODE_KFMAXBW);
+  sf->encode_breakout_thresh = 1;
+
   if (speed == 1) {
     sf->use_square_partition_only = !frame_is_intra_only(cm);
     sf->less_rectangular_check = 1;
@@ -765,6 +767,7 @@
     sf->intra_y_mode_mask[TX_32X32] = INTRA_DC_H_V;
     sf->intra_uv_mode_mask[TX_32X32] = INTRA_DC_H_V;
     sf->intra_uv_mode_mask[TX_16X16] = INTRA_DC_H_V;
+    sf->encode_breakout_thresh = 8;
   }
   if (speed >= 2) {
     sf->use_square_partition_only = !frame_is_intra_only(cm);
@@ -804,6 +807,7 @@
     sf->intra_y_mode_mask[TX_16X16] = INTRA_DC_H_V;
     sf->intra_uv_mode_mask[TX_32X32] = INTRA_DC_H_V;
     sf->intra_uv_mode_mask[TX_16X16] = INTRA_DC_H_V;
+    sf->encode_breakout_thresh = 200;
   }
   if (speed >= 3) {
     sf->use_square_partition_only = 1;
@@ -826,11 +830,13 @@
     sf->use_fast_coef_updates = 2;
     sf->adaptive_rd_thresh = 4;
     sf->mode_skip_start = 6;
+    sf->encode_breakout_thresh = 400;
   }
   if (speed >= 4) {
     sf->optimize_coefficients = 0;
     sf->disable_split_mask = DISABLE_ALL_SPLIT;
     sf->use_fast_lpf_pick = 2;
+    sf->encode_breakout_thresh = 700;
   }
   if (speed >= 5) {
     int i;
@@ -843,10 +849,12 @@
       sf->intra_uv_mode_mask[i] = INTRA_DC_ONLY;
     }
     sf->frame_parameter_update = 0;
+    sf->encode_breakout_thresh = 1000;
   }
   if (speed >= 6) {
     sf->always_this_block_size = BLOCK_16X16;
     sf->use_pick_mode = 1;
+    sf->encode_breakout_thresh = 1000;
   }
 }
 
@@ -906,6 +914,7 @@
   sf->using_small_partition_info = 0;
   sf->mode_skip_start = MAX_MODES;  // Mode index at which mode skip mask set
   sf->use_pick_mode = 0;
+  sf->encode_breakout_thresh = 0;
 
   switch (cpi->oxcf.mode) {
     case MODE_BESTQUALITY:
@@ -949,6 +958,10 @@
   }
 
   cpi->mb.optimize = cpi->sf.optimize_coefficients == 1 && cpi->pass != 1;
+
+  if (cpi->encode_breakout && cpi->oxcf.mode == MODE_REALTIME &&
+      sf->encode_breakout_thresh > cpi->encode_breakout)
+    cpi->encode_breakout = sf->encode_breakout_thresh;
 }
 
 static void alloc_raw_frame_buffers(VP9_COMP *cpi) {
@@ -1408,6 +1421,7 @@
     for (i = 0; i < MAX_SEGMENTS; i++)
       cpi->segment_encode_breakout[i] = cpi->oxcf.encode_breakout;
   }
+  cpi->encode_breakout = cpi->oxcf.encode_breakout;
 
   // local file playback mode == really big buffer
   if (cpi->oxcf.end_usage == USAGE_LOCAL_FILE_PLAYBACK) {
@@ -1848,7 +1862,7 @@
 
   cpi->output_pkt_list = oxcf->output_pkt_list;
 
-  cpi->enable_encode_breakout = 1;
+  cpi->allow_encode_breakout = ENCODE_BREAKOUT_ENABLED;
 
   if (cpi->pass == 1) {
     vp9_init_first_pass(cpi);
@@ -3398,7 +3412,7 @@
 
 static void Pass2Encode(VP9_COMP *cpi, size_t *size,
                         uint8_t *dest, unsigned int *frame_flags) {
-  cpi->enable_encode_breakout = 1;
+  cpi->allow_encode_breakout = ENCODE_BREAKOUT_ENABLED;
 
   vp9_rc_get_second_pass_params(cpi);
   encode_frame_to_data_rate(cpi, size, dest, frame_flags);
--- a/vp9/encoder/vp9_onyx_int.h
+++ b/vp9/encoder/vp9_onyx_int.h
@@ -208,6 +208,15 @@
   ALLOW_RECODE = 3,
 } RECODE_LOOP_TYPE;
 
+typedef enum {
+  // encode_breakout is disabled.
+  ENCODE_BREAKOUT_DISABLED = 0,
+  // encode_breakout is enabled.
+  ENCODE_BREAKOUT_ENABLED = 1,
+  // encode_breakout is enabled with small max_thresh limit.
+  ENCODE_BREAKOUT_LIMITED = 2
+} ENCODE_BREAKOUT_TYPE;
+
 typedef struct {
   // Frame level coding parameter update
   int frame_parameter_update;
@@ -392,6 +401,10 @@
 
   // This flag controls the use of non-RD mode decision.
   int use_pick_mode;
+
+  // This variable sets the encode_breakout threshold. Currently, it is only
+  // enabled in real time mode.
+  int encode_breakout_thresh;
 } SPEED_FEATURES;
 
 typedef struct {
@@ -546,6 +559,13 @@
   unsigned int max_mv_magnitude;
   int mv_step_param;
 
+  // Default value is 1. From first pass stats, encode_breakout may be disabled.
+  ENCODE_BREAKOUT_TYPE allow_encode_breakout;
+
+  // Get threshold from external input. In real time mode, it can be
+  // overwritten according to encoding speed.
+  int encode_breakout;
+
   unsigned char *segmentation_map;
 
   // segment threashold for encode breakout
@@ -635,9 +655,6 @@
     // temporal layers for now.
     LAYER_CONTEXT layer_context[VPX_TS_MAX_LAYERS];
   } svc;
-
-  int enable_encode_breakout;   // Default value is 1. From first pass stats,
-                                // encode_breakout may be disabled.
 
 #if CONFIG_MULTIPLE_ARF
   // ARF tracking variables.
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -2906,33 +2906,26 @@
   if (cm->interp_filter == SWITCHABLE)
     *rate2 += get_switchable_rate(x);
 
-  if (!is_comp_pred && cpi->enable_encode_breakout) {
+  if (!is_comp_pred) {
     if (cpi->active_map_enabled && x->active_ptr[0] == 0)
       x->skip = 1;
-    else if (x->encode_breakout) {
+    else if (cpi->allow_encode_breakout && x->encode_breakout) {
       const BLOCK_SIZE y_size = get_plane_block_size(bsize, &xd->plane[0]);
       const BLOCK_SIZE uv_size = get_plane_block_size(bsize, &xd->plane[1]);
       unsigned int var, sse;
       // Skipping threshold for ac.
       unsigned int thresh_ac;
+      // Set a maximum for threshold to avoid big PSNR loss in low bitrate case.
+      // Use extreme low threshold for static frames to limit skipping.
+      const unsigned int max_thresh = (cpi->allow_encode_breakout ==
+                                      ENCODE_BREAKOUT_LIMITED) ? 128 : 36000;
       // The encode_breakout input
-      unsigned int encode_breakout = x->encode_breakout << 4;
-      unsigned int max_thresh = 36000;
+      const unsigned int min_thresh = ((x->encode_breakout << 4) > max_thresh) ?
+                                      max_thresh : (x->encode_breakout << 4);
 
-      // Use extreme low threshold for static frames to limit skipping.
-      if (cpi->enable_encode_breakout == 2)
-        max_thresh = 128;
-
       // Calculate threshold according to dequant value.
       thresh_ac = (xd->plane[0].dequant[1] * xd->plane[0].dequant[1]) / 9;
-
-      // Use encode_breakout input if it is bigger than internal threshold.
-      if (thresh_ac < encode_breakout)
-        thresh_ac = encode_breakout;
-
-      // Set a maximum for threshold to avoid big PSNR loss in low bitrate case.
-      if (thresh_ac > max_thresh)
-        thresh_ac = max_thresh;
+      thresh_ac = clamp(thresh_ac, min_thresh, max_thresh);
 
       var = cpi->fn_ptr[y_size].vf(x->plane[0].src.buf, x->plane[0].src.stride,
                                    xd->plane[0].dst.buf,