shithub: libvpx

Download patch

ref: e078c3d8546182cc2cc793053476a2e3caa50b4c
parent: e55f60240ac62455c61160e824660c0d22f8f7ed
author: Marco Paniconi <marpan@google.com>
date: Wed Oct 2 13:13:59 EDT 2013

Initial 1-pass.

Change-Id: I58c5436f5c95f6012fb2891cd2a02f76e4870b6a

--- a/test/datarate_test.cc
+++ b/test/datarate_test.cc
@@ -176,6 +176,60 @@
   }
 }
 
-VP8_INSTANTIATE_TEST_CASE(DatarateTest, ALL_TEST_MODES);
+class DatarateTestVP9 : public DatarateTest {
+ protected:
+  virtual ~DatarateTestVP9() {}
 
+  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+                                    ::libvpx_test::Encoder *encoder) {
+    if (video->frame() == 1) {
+      encoder->Control(VP8E_SET_CPUUSED, 2);
+    }
+    const vpx_rational_t tb = video->timebase();
+    timebase_ = static_cast<double>(tb.num) / tb.den;
+    duration_ = 0;
+  }
+
+  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+    const int frame_size_in_bits = pkt->data.frame.sz * 8;
+    bits_total_ += frame_size_in_bits;
+    // Update the most recent pts.
+    last_pts_ = pkt->data.frame.pts;
+    ++frame_number_;
+  }
+
+  virtual void EndPassHook(void) {
+    if (bits_total_) {
+      duration_ = (last_pts_ + 1) * timebase_;
+      // Effective file datarate:
+      effective_datarate_ = ((bits_total_) / 1000.0) / duration_;
+    }
+  }
+};
+
+// There is no buffer model/frame dropper in VP9 currently, so for now we
+// have separate test for VP9 rate targeting for 1-pass CBR. We only check
+// that effective datarate is within some range of target bitrate.
+// No frame dropper, so we can't go to low bitrates.
+TEST_P(DatarateTestVP9, BasicRateTargeting) {
+  cfg_.rc_min_quantizer = 0;
+  cfg_.rc_max_quantizer = 63;
+  cfg_.rc_end_usage = VPX_CBR;
+
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, 140);
+  for (int i = 200; i < 800; i += 200) {
+    cfg_.rc_target_bitrate = i;
+    ResetModel();
+    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+    ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.8)
+        << " The datarate for the file exceeds the target by too much!";
+    ASSERT_LE(cfg_.rc_target_bitrate, effective_datarate_ * 1.3)
+        << " The datarate for the file missed the target!";
+  }
+}
+
+VP8_INSTANTIATE_TEST_CASE(DatarateTest, ALL_TEST_MODES);
+VP9_INSTANTIATE_TEST_CASE(DatarateTestVP9,
+                          ::testing::Values(::libvpx_test::kOnePassGood));
 }  // namespace
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -951,6 +951,12 @@
     sf->optimize_coefficients = 0;
   }
 
+  // No recode for 1 pass.
+  if (cpi->pass == 0) {
+    sf->recode_loop = 0;
+    sf->optimize_coefficients = 0;
+  }
+
   cpi->mb.fwd_txm16x16  = vp9_short_fdct16x16;
   cpi->mb.fwd_txm8x8    = vp9_short_fdct8x8;
   cpi->mb.fwd_txm4x4    = vp9_short_fdct4x4;
@@ -1215,6 +1221,12 @@
 
   switch (cpi->oxcf.Mode) {
       // Real time and one pass deprecated in test code base
+    case MODE_GOODQUALITY:
+      cpi->pass = 0;
+      cpi->compressor_speed = 2;
+      cpi->oxcf.cpu_used = clamp(cpi->oxcf.cpu_used, -5, 5);
+      break;
+
     case MODE_FIRSTPASS:
       cpi->pass = 1;
       cpi->compressor_speed = 1;
@@ -2736,6 +2748,10 @@
 #endif
 #else
       cpi->active_best_quality = inter_minq[q];
+      // 1-pass: for now, use the average Q for the active_best, if its lower
+      // than active_worst.
+      if (cpi->pass == 0 && (cpi->avg_frame_qindex < cpi->active_worst_quality))
+        cpi->active_best_quality = inter_minq[cpi->avg_frame_qindex];
 #endif
 
       // For the constrained quality mode we don't want
@@ -2784,8 +2800,15 @@
   } else if ((cm->frame_type == KEY_FRAME) && cpi->this_key_frame_forced) {
     q = cpi->last_boosted_qindex;
   } else {
-    // Determine initial Q to try
-    q = vp9_regulate_q(cpi, cpi->this_frame_target);
+    // Determine initial Q to try.
+    if (cpi->pass == 0) {
+      // 1-pass: for now, use per-frame-bw for target size of frame, scaled
+      // by |x| for key frame.
+      int scale = (cm->frame_type == KEY_FRAME) ? 5 : 1;
+      q = vp9_regulate_q(cpi, scale * cpi->av_per_frame_bandwidth);
+    } else {
+      q = vp9_regulate_q(cpi, cpi->this_frame_target);
+    }
     if (q > *top_index)
       q = *top_index;
   }
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -256,7 +256,7 @@
 
   switch (cfg.g_pass) {
     case VPX_RC_ONE_PASS:
-      oxcf->Mode = MODE_BESTQUALITY;
+      oxcf->Mode = MODE_GOODQUALITY;
       break;
     case VPX_RC_FIRST_PASS:
       oxcf->Mode = MODE_FIRSTPASS;
@@ -282,6 +282,8 @@
     oxcf->end_usage      = USAGE_CONSTRAINED_QUALITY;
   else if (cfg.rc_end_usage == VPX_Q)
     oxcf->end_usage      = USAGE_CONSTANT_QUALITY;
+  else if (cfg.rc_end_usage == VPX_CBR)
+    oxcf->end_usage = USAGE_STREAM_FROM_SERVER;
 
   oxcf->target_bandwidth         = cfg.rc_target_bitrate;
   oxcf->rc_max_intra_bitrate_pct = vp8_cfg.rc_max_intra_bitrate_pct;