Merge changes I95159bcb,Ia74e3097,I661f6439 * changes: x86/convolve.h: remove redundant check in FUN_CONV_2D x86/convolve.h: replace while w/if for w < 16 x86/convolve.h: change filter[] || chains to |
diff --git a/CHANGELOG b/CHANGELOG index 7746cc6..7db420e 100644 --- a/CHANGELOG +++ b/CHANGELOG
@@ -1,3 +1,7 @@ +Next Release + - Incompatible changes: + The VP9 encoder's default keyframe interval changed to 128 from 9999. + 2015-11-09 v1.5.0 "Javan Whistling Duck" This release improves upon the VP9 encoder and speeds up the encoding and decoding processes.
diff --git a/test/altref_test.cc b/test/altref_test.cc index af25b72..657b893 100644 --- a/test/altref_test.cc +++ b/test/altref_test.cc
@@ -14,6 +14,8 @@ #include "test/util.h" namespace { +#if CONFIG_VP8_ENCODER + // lookahead range: [kLookAheadMin, kLookAheadMax). const int kLookAheadMin = 5; const int kLookAheadMax = 26; @@ -63,7 +65,106 @@ EXPECT_GE(altref_count(), 1); } - VP8_INSTANTIATE_TEST_CASE(AltRefTest, ::testing::Range(kLookAheadMin, kLookAheadMax)); + +#endif // CONFIG_VP8_ENCODER + +class AltRefForcedKeyTest + : public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> { + protected: + AltRefForcedKeyTest() + : EncoderTest(GET_PARAM(0)), + encoding_mode_(GET_PARAM(1)), + cpu_used_(GET_PARAM(2)), + forced_kf_frame_num_(1), + frame_num_(0) {} + virtual ~AltRefForcedKeyTest() {} + + virtual void SetUp() { + InitializeConfig(); + SetMode(encoding_mode_); + cfg_.rc_end_usage = VPX_VBR; + cfg_.g_threads = 0; + } + + virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, + ::libvpx_test::Encoder *encoder) { + if (video->frame() == 0) { + encoder->Control(VP8E_SET_CPUUSED, cpu_used_); + encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1); + // override test default for tile columns if necessary. +#if CONFIG_VP9_ENCODER + if (GET_PARAM(0) == &libvpx_test::kVP9) { + encoder->Control(VP9E_SET_TILE_COLUMNS, 6); + } +#endif +#if CONFIG_VP10_ENCODER + if (GET_PARAM(0) == &libvpx_test::kVP10) { + encoder->Control(VP9E_SET_TILE_COLUMNS, 6); + } +#endif + } + frame_flags_ = + (video->frame() == forced_kf_frame_num_) ? VPX_EFLAG_FORCE_KF : 0; + } + + virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) { + if (frame_num_ == forced_kf_frame_num_) { + ASSERT_TRUE(!!(pkt->data.frame.flags & VPX_FRAME_IS_KEY)) + << "Frame #" << frame_num_ << " isn't a keyframe!"; + } + ++frame_num_; + } + + ::libvpx_test::TestMode encoding_mode_; + int cpu_used_; + unsigned int forced_kf_frame_num_; + unsigned int frame_num_; +}; + +TEST_P(AltRefForcedKeyTest, Frame1IsKey) { + const vpx_rational timebase = { 1, 30 }; + const int lag_values[] = { 3, 15, 25, -1 }; + + forced_kf_frame_num_ = 1; + for (int i = 0; lag_values[i] != -1; ++i) { + frame_num_ = 0; + cfg_.g_lag_in_frames = lag_values[i]; + libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + timebase.den, timebase.num, 0, 30); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + } +} + +TEST_P(AltRefForcedKeyTest, ForcedFrameIsKey) { + const vpx_rational timebase = { 1, 30 }; + const int lag_values[] = { 3, 15, 25, -1 }; + + for (int i = 0; lag_values[i] != -1; ++i) { + frame_num_ = 0; + forced_kf_frame_num_ = lag_values[i] - 1; + cfg_.g_lag_in_frames = lag_values[i]; + libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + timebase.den, timebase.num, 0, 30); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + } +} + +VP8_INSTANTIATE_TEST_CASE( + AltRefForcedKeyTest, + ::testing::Values(::libvpx_test::kOnePassGood), + ::testing::Range(0, 9)); + +VP9_INSTANTIATE_TEST_CASE( + AltRefForcedKeyTest, + ::testing::Values(::libvpx_test::kOnePassGood), + ::testing::Range(0, 9)); + +VP10_INSTANTIATE_TEST_CASE( + AltRefForcedKeyTest, + ::testing::Values(::libvpx_test::kOnePassGood), + ::testing::Range(0, 9)); + } // namespace
diff --git a/test/datarate_test.cc b/test/datarate_test.cc index 9d5074e..1498923 100644 --- a/test/datarate_test.cc +++ b/test/datarate_test.cc
@@ -519,6 +519,9 @@ cfg_.rc_end_usage = VPX_CBR; cfg_.rc_target_bitrate = 200; cfg_.g_lag_in_frames = 0; + // TODO(marpan): Investigate datarate target failures with a smaller keyframe + // interval (128). + cfg_.kf_max_dist = 9999; ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 30, 1, 0, 140); @@ -774,10 +777,6 @@ svc_params_.max_quantizers[i] = 63; svc_params_.min_quantizers[i] = 0; } - svc_params_.scaling_factor_num[0] = 144; - svc_params_.scaling_factor_den[0] = 288; - svc_params_.scaling_factor_num[1] = 288; - svc_params_.scaling_factor_den[1] = 288; encoder->Control(VP9E_SET_SVC, 1); encoder->Control(VP9E_SET_SVC_PARAMETERS, &svc_params_); encoder->Control(VP8E_SET_CPUUSED, speed_setting_); @@ -884,7 +883,7 @@ // Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and // 3 temporal layers. Run CIF clip with 1 thread. -TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc) { +TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayers) { cfg_.rc_buf_initial_sz = 500; cfg_.rc_buf_optimal_sz = 500; cfg_.rc_buf_sz = 1000; @@ -905,6 +904,9 @@ svc_params_.scaling_factor_num[1] = 288; svc_params_.scaling_factor_den[1] = 288; cfg_.rc_dropframe_thresh = 10; + // TODO(marpan): another test should be added for default/small kf_max_dist + // once https://bugs.chromium.org/p/webm/issues/detail?id=1150 is fixed. + cfg_.kf_max_dist = 9999; ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 30, 1, 0, 200); // TODO(wonkap/marpan): Check that effective_datarate for each layer hits the @@ -923,9 +925,49 @@ } } +// Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and +// 3 temporal layers. Run CIF clip with 1 thread. +TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayers) { + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_min_quantizer = 0; + cfg_.rc_max_quantizer = 63; + cfg_.rc_end_usage = VPX_CBR; + cfg_.g_lag_in_frames = 0; + cfg_.ss_number_layers = 3; + cfg_.ts_number_layers = 3; + cfg_.ts_rate_decimator[0] = 4; + cfg_.ts_rate_decimator[1] = 2; + cfg_.ts_rate_decimator[2] = 1; + cfg_.g_error_resilient = 1; + cfg_.g_threads = 1; + cfg_.temporal_layering_mode = 3; + svc_params_.scaling_factor_num[0] = 72; + svc_params_.scaling_factor_den[0] = 288; + svc_params_.scaling_factor_num[1] = 144; + svc_params_.scaling_factor_den[1] = 288; + svc_params_.scaling_factor_num[2] = 288; + svc_params_.scaling_factor_den[2] = 288; + cfg_.rc_dropframe_thresh = 10; + cfg_.kf_max_dist = 9999; + ::libvpx_test::I420VideoSource video("niklas_1280_720_30.y4m", 1280, 720, + 30, 1, 0, 300); + cfg_.rc_target_bitrate = 800; + ResetModel(); + assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, + cfg_.ts_number_layers, cfg_.temporal_layering_mode); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.85) + << " The datarate for the file exceeds the target by too much!"; + ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.17) + << " The datarate for the file is lower than the target by too much!"; + EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0); +} + // Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and // 3 temporal layers. Run HD clip with 4 threads. -TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc4threads) { +TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayers4threads) { cfg_.rc_buf_initial_sz = 500; cfg_.rc_buf_optimal_sz = 500; cfg_.rc_buf_sz = 1000; @@ -946,6 +988,7 @@ svc_params_.scaling_factor_num[1] = 288; svc_params_.scaling_factor_den[1] = 288; cfg_.rc_dropframe_thresh = 10; + cfg_.kf_max_dist = 9999; ::libvpx_test::I420VideoSource video("niklas_1280_720_30.y4m", 1280, 720, 30, 1, 0, 300); cfg_.rc_target_bitrate = 800; @@ -960,6 +1003,46 @@ EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0); } +// Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and +// 3 temporal layers. Run HD clip with 4 threads. +TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayers4threads) { + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_min_quantizer = 0; + cfg_.rc_max_quantizer = 63; + cfg_.rc_end_usage = VPX_CBR; + cfg_.g_lag_in_frames = 0; + cfg_.ss_number_layers = 3; + cfg_.ts_number_layers = 3; + cfg_.ts_rate_decimator[0] = 4; + cfg_.ts_rate_decimator[1] = 2; + cfg_.ts_rate_decimator[2] = 1; + cfg_.g_error_resilient = 1; + cfg_.g_threads = 4; + cfg_.temporal_layering_mode = 3; + svc_params_.scaling_factor_num[0] = 72; + svc_params_.scaling_factor_den[0] = 288; + svc_params_.scaling_factor_num[1] = 144; + svc_params_.scaling_factor_den[1] = 288; + svc_params_.scaling_factor_num[2] = 288; + svc_params_.scaling_factor_den[2] = 288; + cfg_.rc_dropframe_thresh = 10; + cfg_.kf_max_dist = 9999; + ::libvpx_test::I420VideoSource video("niklas_1280_720_30.y4m", 1280, 720, + 30, 1, 0, 300); + cfg_.rc_target_bitrate = 800; + ResetModel(); + assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, + cfg_.ts_number_layers, cfg_.temporal_layering_mode); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.85) + << " The datarate for the file exceeds the target by too much!"; + ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.17) + << " The datarate for the file is lower than the target by too much!"; + EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0); +} + VP8_INSTANTIATE_TEST_CASE(DatarateTestLarge, ALL_TEST_MODES); VP9_INSTANTIATE_TEST_CASE(DatarateTestVP9Large, ::testing::Values(::libvpx_test::kOnePassGood,
diff --git a/test/test.mk b/test/test.mk index e8e8304..0a4b69c 100644 --- a/test/test.mk +++ b/test/test.mk
@@ -18,6 +18,7 @@ LIBVPX_TEST_SRCS-yes += ../md5_utils.h ../md5_utils.c LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += ivf_video_source.h LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += ../y4minput.h ../y4minput.c +LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += altref_test.cc LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += aq_segment_test.cc LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += datarate_test.cc LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += encode_api_test.cc @@ -27,7 +28,6 @@ LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += y4m_video_source.h LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += yuv_video_source.h -LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += altref_test.cc LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += config_test.cc LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += cq_test.cc LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += keyframe_test.cc
diff --git a/vp10/encoder/encoder.c b/vp10/encoder/encoder.c index 775fd22..31a9390 100644 --- a/vp10/encoder/encoder.c +++ b/vp10/encoder/encoder.c
@@ -4008,6 +4008,20 @@ arf_src_index = get_arf_src_index(cpi); if (arf_src_index) { + for (i = 0; i <= arf_src_index; ++i) { + struct lookahead_entry *e = vp10_lookahead_peek(cpi->lookahead, i); + // Avoid creating an alt-ref if there's a forced keyframe pending. + if (e == NULL) { + break; + } else if (e->flags == VPX_EFLAG_FORCE_KF) { + arf_src_index = 0; + flush = 1; + break; + } + } + } + + if (arf_src_index) { assert(arf_src_index <= rc->frames_to_key); if ((source = vp10_lookahead_peek(cpi->lookahead, arf_src_index)) != NULL) {
diff --git a/vp8/encoder/denoising.c b/vp8/encoder/denoising.c index 113865f..5ae44e8 100644 --- a/vp8/encoder/denoising.c +++ b/vp8/encoder/denoising.c
@@ -23,7 +23,7 @@ */ static const unsigned int SSE_DIFF_THRESHOLD = 16 * 16 * 20; static const unsigned int SSE_THRESHOLD = 16 * 16 * 40; -static const unsigned int SSE_THRESHOLD_HIGH = 16 * 16 * 60; +static const unsigned int SSE_THRESHOLD_HIGH = 16 * 16 * 80; /* * The filter function was modified to reduce the computational complexity.
diff --git a/vp8/encoder/denoising.h b/vp8/encoder/denoising.h index 9a379a6..f13d52f 100644 --- a/vp8/encoder/denoising.h +++ b/vp8/encoder/denoising.h
@@ -18,8 +18,8 @@ extern "C" { #endif -#define SUM_DIFF_THRESHOLD (16 * 16 * 2) -#define SUM_DIFF_THRESHOLD_HIGH (600) // ~(16 * 16 * 1.5) +#define SUM_DIFF_THRESHOLD 384 +#define SUM_DIFF_THRESHOLD_HIGH 512 #define MOTION_MAGNITUDE_THRESHOLD (8*3) #define SUM_DIFF_THRESHOLD_UV (96) // (8 * 8 * 1.5)
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index 4109c19..cff1afe 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c
@@ -770,6 +770,7 @@ x->pred_mv[LAST_FRAME] = mi->mv[0].as_mv; } + set_ref_ptrs(cm, xd, mi->ref_frame[0], mi->ref_frame[1]); vp9_build_inter_predictors_sb(xd, mi_row, mi_col, BLOCK_64X64); // Check if most of the superblock is skin content, and if so, force split
diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index e2277ca..f8f681a 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c
@@ -4378,6 +4378,20 @@ arf_src_index = 0; if (arf_src_index) { + for (i = 0; i <= arf_src_index; ++i) { + struct lookahead_entry *e = vp9_lookahead_peek(cpi->lookahead, i); + // Avoid creating an alt-ref if there's a forced keyframe pending. + if (e == NULL) { + break; + } else if (e->flags == VPX_EFLAG_FORCE_KF) { + arf_src_index = 0; + flush = 1; + break; + } + } + } + + if (arf_src_index) { assert(arf_src_index <= rc->frames_to_key); if ((source = vp9_lookahead_peek(cpi->lookahead, arf_src_index)) != NULL) {
diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c index 11df1e4..624d5c9 100644 --- a/vp9/vp9_cx_iface.c +++ b/vp9/vp9_cx_iface.c
@@ -1566,7 +1566,7 @@ // keyframing settings (kf) VPX_KF_AUTO, // g_kfmode 0, // kf_min_dist - 9999, // kf_max_dist + 128, // kf_max_dist VPX_SS_DEFAULT_LAYERS, // ss_number_layers {0},
diff --git a/vpxenc.c b/vpxenc.c index f14470a..f24b180 100644 --- a/vpxenc.c +++ b/vpxenc.c
@@ -804,7 +804,6 @@ int arg_ctrls[ARG_CTRL_CNT_MAX][2]; int arg_ctrl_cnt; int write_webm; - int have_kf_max_dist; #if CONFIG_VP9_HIGHBITDEPTH // whether to use 16bit internal buffers int use_16bit_internal; @@ -1224,7 +1223,6 @@ config->cfg.kf_min_dist = arg_parse_uint(&arg); } else if (arg_match(&arg, &kf_max_dist, argi)) { config->cfg.kf_max_dist = arg_parse_uint(&arg); - config->have_kf_max_dist = 1; } else if (arg_match(&arg, &kf_disabled, argi)) { config->cfg.kf_mode = VPX_KF_DISABLED; #if CONFIG_VP9_HIGHBITDEPTH @@ -1352,19 +1350,6 @@ } } - -static void set_default_kf_interval(struct stream_state *stream, - struct VpxEncoderConfig *global) { - /* Use a max keyframe interval of 5 seconds, if none was - * specified on the command line. - */ - if (!stream->config.have_kf_max_dist) { - double framerate = (double)global->framerate.num / global->framerate.den; - if (framerate > 0.0) - stream->config.cfg.kf_max_dist = (unsigned int)(5.0 * framerate); - } -} - static const char* file_type_to_string(enum VideoFileType t) { switch (t) { case FILE_TYPE_RAW: return "RAW"; @@ -2086,8 +2071,6 @@ stream->config.cfg.g_timebase.num = global.framerate.den); } - FOREACH_STREAM(set_default_kf_interval(stream, &global)); - /* Show configuration */ if (global.verbose && pass == 0) FOREACH_STREAM(show_stream_config(stream, &global, &input));