*/
#include "./vpx_config.h"
#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/acm_random.h"
#include "test/codec_factory.h"
#include "test/encode_test_driver.h"
#include "test/i420_video_source.h"
<< " The datarate for the file is greater than target by too much!";
}
+using libvpx_test::ACMRandom;
+
+class DatarateTestVP9FrameQp
+ : public DatarateTestVP9,
+ public ::testing::TestWithParam<const libvpx_test::CodecFactory *> {
+ public:
+ DatarateTestVP9FrameQp() : DatarateTestVP9(GetParam()), frame_(0) {}
+ virtual ~DatarateTestVP9FrameQp() {}
+
+ protected:
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(::libvpx_test::kRealTime);
+ ResetModel();
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ set_cpu_used_ = 7;
+ DatarateTestVP9::PreEncodeFrameHook(video, encoder);
+ ACMRandom rnd;
+ frame_qp_ = static_cast<int>(rnd.RandRange(64));
+ encoder->Control(VP9E_SET_QUANTIZER_ONE_PASS, frame_qp_);
+ frame_++;
+ }
+
+ virtual void PostEncodeFrameHook(::libvpx_test::Encoder *encoder) {
+ int qp = 0;
+ if (frame_ >= total_frame_) return;
+ encoder->Control(VP8E_GET_LAST_QUANTIZER_64, &qp);
+ ASSERT_EQ(frame_qp_, qp);
+ }
+
+ protected:
+ int total_frame_;
+
+ private:
+ int frame_qp_;
+ int frame_;
+};
+
+TEST_P(DatarateTestVP9FrameQp, VP9SetFrameQp) {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_dropframe_thresh = 0;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+
+ total_frame_ = 400;
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, total_frame_);
+ ResetModel();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+TEST_P(DatarateTestVP9FrameQp, VP9SetFrameQp3TemporalLayers) {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_dropframe_thresh = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+
+ // 3 Temporal layers, no spatial layers: Framerate decimation (4, 2, 1).
+ cfg_.ss_number_layers = 1;
+ cfg_.ts_number_layers = 3;
+ cfg_.ts_rate_decimator[0] = 4;
+ cfg_.ts_rate_decimator[1] = 2;
+ cfg_.ts_rate_decimator[2] = 1;
+
+ cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
+ cfg_.rc_target_bitrate = 200;
+ total_frame_ = 400;
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, total_frame_);
+ ResetModel();
+ cfg_.layer_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
+ cfg_.layer_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
+ cfg_.layer_target_bitrate[2] = cfg_.rc_target_bitrate;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
#if CONFIG_VP9_TEMPORAL_DENOISING
// Params: speed setting.
class DatarateTestVP9RealTimeDenoiser : public DatarateTestVP9RealTime {
VP9_INSTANTIATE_TEST_SUITE(DatarateTestVP9RealTime, ::testing::Range(5, 10));
+#if CONFIG_VP9
+INSTANTIATE_TEST_SUITE_P(
+ VP9, DatarateTestVP9FrameQp,
+ ::testing::Values(
+ static_cast<const libvpx_test::CodecFactory *>(&libvpx_test::kVP9)));
+#endif
+
VP9_INSTANTIATE_TEST_SUITE(DatarateTestVP9RealTimeDeltaQUV,
::testing::Range(5, 10),
::testing::Values(-5, -10, -15));
va_list args) {
struct vp9_extracfg extra_cfg = ctx->extra_cfg;
extra_cfg.aq_mode = CAST(VP9E_SET_AQ_MODE, args);
+ if (ctx->cpi->fixed_qp_onepass) extra_cfg.aq_mode = 0;
return update_extra_cfg(ctx, &extra_cfg);
}
return VPX_CODEC_OK;
}
+static vpx_codec_err_t ctrl_set_quantizer_one_pass(vpx_codec_alg_priv_t *ctx,
+ va_list args) {
+ VP9_COMP *const cpi = ctx->cpi;
+ const int qp = va_arg(args, int);
+ vpx_codec_enc_cfg_t *cfg = &ctx->cfg;
+ struct vp9_extracfg extra_cfg = ctx->extra_cfg;
+ vpx_codec_err_t res;
+
+ if (qp < 0 || qp > 63) return VPX_CODEC_INVALID_PARAM;
+
+ cfg->rc_min_quantizer = cfg->rc_max_quantizer = qp;
+ extra_cfg.aq_mode = 0;
+ cpi->fixed_qp_onepass = 1;
+
+ res = update_extra_cfg(ctx, &extra_cfg);
+ return res;
+}
+
static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
{ VP8_COPY_REFERENCE, ctrl_copy_reference },
{ VP9E_SET_DISABLE_LOOPFILTER, ctrl_set_disable_loopfilter },
{ VP9E_SET_RTC_EXTERNAL_RATECTRL, ctrl_set_rtc_external_ratectrl },
{ VP9E_SET_EXTERNAL_RATE_CONTROL, ctrl_set_external_rate_control },
+ { VP9E_SET_QUANTIZER_ONE_PASS, ctrl_set_quantizer_one_pass },
// Getters
{ VP8E_GET_LAST_QUANTIZER, ctrl_get_quantizer },
* Supported in codecs: VP8
*/
VP8E_SET_RTC_EXTERNAL_RATECTRL,
+
+ /*!\brief Codec control to set quantizer for the next frame.
+ *
+ * This will turn off cyclic refresh. Only applicable to 1-pass without
+ * spatial layers.
+ *
+ * Supported in codecs: VP9
+ *
+ */
+ VP9E_SET_QUANTIZER_ONE_PASS,
};
/*!\brief vpx 1-D scaling mode
#define VPX_CTRL_VP9E_GET_LAST_QUANTIZER_SVC_LAYERS
VPX_CTRL_USE_TYPE(VP8E_SET_RTC_EXTERNAL_RATECTRL, int)
#define VPX_CTRL_VP8E_SET_RTC_EXTERNAL_RATECTRL
+VPX_CTRL_USE_TYPE(VP9E_SET_QUANTIZER_ONE_PASS, int)
+#define VPX_CTRL_VP9E_SET_QUANTIZER_ONE_PASS
/*!\endcond */
/*! @} - end defgroup vp8_encoder */