ref: f0ccaff5538c50d0b4a2356386b941eea12f038d
parent: 6bff6cb5a9efe88c2cbe2c5f967560f68ee3ce29
parent: 863f860bfcf3bdc26eeecb299aa481d0f63d11ac
author: Marco Paniconi <marpan@google.com>
date: Thu Apr 13 20:45:41 EDT 2017
Merge "vp9: Avoid encoder loopfilter for non-reference frames."
--- a/test/datarate_test.cc
+++ b/test/datarate_test.cc
@@ -1221,9 +1221,10 @@
}
}
-// Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and 1temporal
-// layer, with screen content mode on and same speed setting for all layers.
-TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2patialLayersScreenContent1) {
+// Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and 1
+// temporal layer, with screen content mode on and same speed setting for all
+// layers.
+TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL1TLScreenContent1) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
@@ -1241,7 +1242,7 @@
svc_params_.scaling_factor_den[0] = 288;
svc_params_.scaling_factor_num[1] = 288;
svc_params_.scaling_factor_den[1] = 288;
- cfg_.rc_dropframe_thresh = 0;
+ cfg_.rc_dropframe_thresh = 10;
cfg_.kf_max_dist = 9999;
::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 300);
cfg_.rc_target_bitrate = 500;
@@ -1256,7 +1257,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, OnePassCbrSvc2SpatialLayers) {
+TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL3TL) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
@@ -1276,7 +1277,7 @@
svc_params_.scaling_factor_den[0] = 288;
svc_params_.scaling_factor_num[1] = 288;
svc_params_.scaling_factor_den[1] = 288;
- cfg_.rc_dropframe_thresh = 10;
+ cfg_.rc_dropframe_thresh = 0;
cfg_.kf_max_dist = 9999;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 200);
@@ -1288,17 +1289,21 @@
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, file_datarate_ * 0.85)
+ ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.82)
<< " The datarate for the file exceeds the target by too much!";
ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.15)
<< " The datarate for the file is lower than the target by too much!";
- EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
+ // Number of temporal layers > 1, so half of the frames in this SVC pattern
+ // will be non-reference frame and hence encoder will avoid loopfilter.
+ // Since frame dropper is off, we can expcet 100 (half of the sequence)
+ // mismatched frames.
+ EXPECT_EQ(static_cast<unsigned int>(100), GetMismatchFrames());
}
}
// Check basic rate targeting for 1 pass CBR SVC with denoising.
// 2 spatial layers and 3 temporal layer. Run HD clip with 2 threads.
-TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayersDenoiserOn) {
+TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL3TLDenoiserOn) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
@@ -1318,7 +1323,7 @@
svc_params_.scaling_factor_den[0] = 288;
svc_params_.scaling_factor_num[1] = 288;
svc_params_.scaling_factor_den[1] = 288;
- cfg_.rc_dropframe_thresh = 10;
+ cfg_.rc_dropframe_thresh = 0;
cfg_.kf_max_dist = 9999;
::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 300);
// TODO(marpan): Check that effective_datarate for each layer hits the
@@ -1330,17 +1335,21 @@
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, file_datarate_ * 0.85)
+ ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.82)
<< " The datarate for the file exceeds the target by too much!";
ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.15)
<< " The datarate for the file is lower than the target by too much!";
- EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
+ // Number of temporal layers > 1, so half of the frames in this SVC pattern
+ // will be non-reference frame and hence encoder will avoid loopfilter.
+ // Since frame dropper is off, we can expcet 150 (half of the sequence)
+ // mismatched frames.
+ EXPECT_EQ(static_cast<unsigned int>(150), GetMismatchFrames());
}
}
// Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and 3
// temporal layers. Run CIF clip with 1 thread, and few short key frame periods.
-TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayersSmallKf) {
+TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL3TLSmallKf) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
@@ -1376,13 +1385,12 @@
<< " The datarate for the file exceeds the target by too much!";
ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.15)
<< " The datarate for the file is lower than the target by too much!";
- EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
}
}
// 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, OnePassCbrSvc2SpatialLayers4threads) {
+TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL3TL4threads) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
@@ -1402,7 +1410,7 @@
svc_params_.scaling_factor_den[0] = 288;
svc_params_.scaling_factor_num[1] = 288;
svc_params_.scaling_factor_den[1] = 288;
- cfg_.rc_dropframe_thresh = 10;
+ cfg_.rc_dropframe_thresh = 0;
cfg_.kf_max_dist = 9999;
::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 300);
cfg_.rc_target_bitrate = 800;
@@ -1410,16 +1418,20 @@
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, file_datarate_ * 0.85)
+ ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.82)
<< " The datarate for the file exceeds the target by too much!";
ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.15)
<< " The datarate for the file is lower than the target by too much!";
- EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
+ // Number of temporal layers > 1, so half of the frames in this SVC pattern
+ // will be non-reference frame and hence encoder will avoid loopfilter.
+ // Since frame dropper is off, we can expcet 150 (half of the sequence)
+ // mismatched frames.
+ EXPECT_EQ(static_cast<unsigned int>(150), GetMismatchFrames());
}
// 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) {
+TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SL3TL) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
@@ -1441,7 +1453,7 @@
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_.rc_dropframe_thresh = 0;
cfg_.kf_max_dist = 9999;
::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 300);
cfg_.rc_target_bitrate = 800;
@@ -1449,16 +1461,20 @@
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, file_datarate_ * 0.85)
+ ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.82)
<< " The datarate for the file exceeds the target by too much!";
ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.22)
<< " The datarate for the file is lower than the target by too much!";
- EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
+ // Number of temporal layers > 1, so half of the frames in this SVC pattern
+ // will be non-reference frame and hence encoder will avoid loopfilter.
+ // Since frame dropper is off, we can expcet 150 (half of the sequence)
+ // mismatched frames.
+ EXPECT_EQ(static_cast<unsigned int>(150), GetMismatchFrames());
}
// Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and 3
// temporal layers. Run CIF clip with 1 thread, and few short key frame periods.
-TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayersSmallKf) {
+TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SL3TLSmallKf) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
@@ -1495,13 +1511,12 @@
<< " The datarate for the file exceeds the target by too much!";
ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.30)
<< " The datarate for the file is lower than the target by too much!";
- EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
}
}
// 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) {
+TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SL3TL4threads) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
@@ -1523,7 +1538,7 @@
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_.rc_dropframe_thresh = 0;
cfg_.kf_max_dist = 9999;
::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 300);
cfg_.rc_target_bitrate = 800;
@@ -1531,16 +1546,20 @@
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, file_datarate_ * 0.85)
+ ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.82)
<< " The datarate for the file exceeds the target by too much!";
ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.22)
<< " The datarate for the file is lower than the target by too much!";
- EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
+ // Number of temporal layers > 1, so half of the frames in this SVC pattern
+ // will be non-reference frame and hence encoder will avoid loopfilter.
+ // Since frame dropper is off, we can expcet 150 (half of the sequence)
+ // mismatched frames.
+ EXPECT_EQ(static_cast<unsigned int>(150), GetMismatchFrames());
}
// Run SVC encoder for 1 temporal layer, 2 spatial layers, with spatial
// downscale 5x5.
-TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayers5x5MultipleRuns) {
+TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL1TL5x5MultipleRuns) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
@@ -1558,7 +1577,7 @@
svc_params_.scaling_factor_den[0] = 1280;
svc_params_.scaling_factor_num[1] = 1280;
svc_params_.scaling_factor_den[1] = 1280;
- cfg_.rc_dropframe_thresh = 0;
+ cfg_.rc_dropframe_thresh = 10;
cfg_.kf_max_dist = 999999;
cfg_.kf_min_dist = 0;
cfg_.ss_target_bitrate[0] = 300;
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -2618,6 +2618,10 @@
MACROBLOCKD *xd = &cpi->td.mb.e_mbd;
struct loopfilter *lf = &cm->lf;
+ const int is_reference_frame =
+ (cpi->refresh_last_frame || cpi->refresh_golden_frame ||
+ cpi->refresh_alt_ref_frame);
+
if (xd->lossless) {
lf->filter_level = 0;
lf->last_filt_level = 0;
@@ -2643,7 +2647,7 @@
cpi->time_pick_lpf += vpx_usec_timer_elapsed(&timer);
}
- if (lf->filter_level > 0) {
+ if (lf->filter_level > 0 && is_reference_frame) {
vp9_build_mask_frame(cm, lf->filter_level, 0);
if (cpi->num_workers > 1)