diff --git a/test/datarate_test.cc b/test/datarate_test.cc index f020a99382ced71b4d6f13788fec9fd19848f00f..6d5064442720960e4c1edaacaf5c3d3045d15de3 100644 --- a/test/datarate_test.cc +++ b/test/datarate_test.cc @@ -176,6 +176,60 @@ TEST_P(DatarateTest, ChangingDropFrameThresh) { } } -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 diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index 43e379d324c9d055596c185af6ccfaeb7b1294f2..ba09622d75cef9df3c47507278985726328e2a67 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -951,6 +951,12 @@ void vp9_set_speed_features(VP9_COMP *cpi) { 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 @@ void vp9_change_config(VP9_PTR ptr, VP9_CONFIG *oxcf) { 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 @@ static int pick_q_and_adjust_q_bounds(VP9_COMP *cpi, #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 @@ static int pick_q_and_adjust_q_bounds(VP9_COMP *cpi, } 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; } diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c index 810fdf51fc8b158c9df8bd2378b8641242d44096..fb380e1db3e205483409f4c4967cf0a5c42a278e 100644 --- a/vp9/vp9_cx_iface.c +++ b/vp9/vp9_cx_iface.c @@ -256,7 +256,7 @@ static vpx_codec_err_t set_vp9e_config(VP9_CONFIG *oxcf, 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 @@ static vpx_codec_err_t set_vp9e_config(VP9_CONFIG *oxcf, 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;