diff options
author | Marco <marpan@google.com> | 2017-12-14 16:35:33 -0800 |
---|---|---|
committer | Marco <marpan@google.com> | 2017-12-19 19:48:47 -0800 |
commit | 9ca9c12dbdea516f46e1e08203d7cc1378eb171b (patch) | |
tree | 022a963d46494eff91054eea4ed954b7c40d06ec | |
parent | a2127236ae4742f329e5571d76b84de08cd3b8ea (diff) | |
download | libvpx-9ca9c12dbdea516f46e1e08203d7cc1378eb171b.tar libvpx-9ca9c12dbdea516f46e1e08203d7cc1378eb171b.tar.gz libvpx-9ca9c12dbdea516f46e1e08203d7cc1378eb171b.tar.bz2 libvpx-9ca9c12dbdea516f46e1e08203d7cc1378eb171b.zip |
vp9-svc: Add layer bitrate targeting to SVC datarate tests.
Modify and update the SVC datarate unittests to verify the
rate targeting for each spatial-temporal layer.
The current tests were only verifying the rate targeting
of the full SVC stream, not individual layers.
Also re-enabled a test that was disabled.
This is a stronger verification of the layered rate control
for SVC for 1 pass CBR encoding.
Added PostEncodeFrameHook, needed to get the layer_id and
update the layer buffer level.
Change-Id: I9fd54ad474686b20a6de3250d587e2cec194a56f
-rw-r--r-- | test/datarate_test.cc | 262 | ||||
-rw-r--r-- | test/encode_test_driver.cc | 2 | ||||
-rw-r--r-- | test/encode_test_driver.h | 2 |
3 files changed, 200 insertions, 66 deletions
diff --git a/test/datarate_test.cc b/test/datarate_test.cc index 4e6fbe4cf..31a8523d2 100644 --- a/test/datarate_test.cc +++ b/test/datarate_test.cc @@ -1216,16 +1216,17 @@ class DatarateOnePassCbrSvc } virtual void ResetModel() { last_pts_ = 0; - bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz; - frame_number_ = 0; - first_drop_ = 0; - bits_total_ = 0; duration_ = 0.0; mismatch_psnr_ = 0.0; mismatch_nframes_ = 0; denoiser_on_ = 0; tune_content_ = 0; base_speed_setting_ = 5; + spatial_layer_id_ = 0; + temporal_layer_id_ = 0; + memset(bits_in_buffer_model_, 0, sizeof(bits_in_buffer_model_)); + memset(bits_total_, 0, sizeof(bits_total_)); + memset(layer_target_avg_bandwidth_, 0, sizeof(layer_target_avg_bandwidth_)); } virtual void BeginPassHook(unsigned int /*pass*/) {} virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, @@ -1256,30 +1257,94 @@ class DatarateOnePassCbrSvc timebase_ = static_cast<double>(tb.num) / tb.den; duration_ = 0; } + + virtual void PostEncodeFrameHook(::libvpx_test::Encoder *encoder) { + vpx_svc_layer_id_t layer_id; + encoder->Control(VP9E_GET_SVC_LAYER_ID, &layer_id); + spatial_layer_id_ = layer_id.spatial_layer_id; + temporal_layer_id_ = layer_id.temporal_layer_id; + // Update buffer with per-layer target frame bandwidth, this is done + // for every frame passed to the encoder (encoded or dropped). + // For temporal layers, update the cumulative buffer level. + for (int sl = 0; sl < number_spatial_layers_; ++sl) { + for (int tl = temporal_layer_id_; tl < number_temporal_layers_; ++tl) { + const int layer = sl * number_temporal_layers_ + tl; + bits_in_buffer_model_[layer] += + static_cast<int64_t>(layer_target_avg_bandwidth_[layer]); + } + } + } + + vpx_codec_err_t parse_superframe_index(const uint8_t *data, size_t data_sz, + uint32_t sizes[8], int *count) { + uint8_t marker; + marker = *(data + data_sz - 1); + *count = 0; + if ((marker & 0xe0) == 0xc0) { + const uint32_t frames = (marker & 0x7) + 1; + const uint32_t mag = ((marker >> 3) & 0x3) + 1; + const size_t index_sz = 2 + mag * frames; + // This chunk is marked as having a superframe index but doesn't have + // enough data for it, thus it's an invalid superframe index. + if (data_sz < index_sz) return VPX_CODEC_CORRUPT_FRAME; + { + const uint8_t marker2 = *(data + data_sz - index_sz); + // This chunk is marked as having a superframe index but doesn't have + // the matching marker byte at the front of the index therefore it's an + // invalid chunk. + if (marker != marker2) return VPX_CODEC_CORRUPT_FRAME; + } + { + uint32_t i, j; + const uint8_t *x = &data[data_sz - index_sz + 1]; + for (i = 0; i < frames; ++i) { + uint32_t this_sz = 0; + + for (j = 0; j < mag; ++j) this_sz |= (*x++) << (j * 8); + sizes[i] = this_sz; + } + *count = frames; + } + } + return VPX_CODEC_OK; + } + virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) { - vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_; - if (last_pts_ == 0) duration = 1; - bits_in_buffer_model_ += static_cast<int64_t>( - duration * timebase_ * cfg_.rc_target_bitrate * 1000); + uint32_t sizes[8] = { 0 }; + int count = 0; + last_pts_ = pkt->data.frame.pts; const bool key_frame = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) ? true : false; - if (!key_frame) { - ASSERT_GE(bits_in_buffer_model_, 0) - << "Buffer Underrun at frame " << pkt->data.frame.pts; + parse_superframe_index(static_cast<const uint8_t *>(pkt->data.frame.buf), + pkt->data.frame.sz, sizes, &count); + ASSERT_EQ(count, number_spatial_layers_); + for (int sl = 0; sl < number_spatial_layers_; ++sl) { + sizes[sl] = sizes[sl] << 3; + // Update the total encoded bits per layer. + // For temporal layers, update the cumulative encoded bits per layer. + for (int tl = temporal_layer_id_; tl < number_temporal_layers_; ++tl) { + const int layer = sl * number_temporal_layers_ + tl; + bits_total_[layer] += static_cast<int64_t>(sizes[sl]); + // Update the per-layer buffer level with the encoded frame size. + bits_in_buffer_model_[layer] -= static_cast<int64_t>(sizes[sl]); + // There should be no buffer underrun, except on the base + // temporal layer, since there may be key frames there. + if (!key_frame && tl > 0) { + ASSERT_GE(bits_in_buffer_model_[layer], 0) + << "Buffer Underrun at frame " << pkt->data.frame.pts; + } + } } - const size_t frame_size_in_bits = pkt->data.frame.sz * 8; - bits_in_buffer_model_ -= static_cast<int64_t>(frame_size_in_bits); - bits_total_ += frame_size_in_bits; - if (!first_drop_ && duration > 1) first_drop_ = last_pts_ + 1; - last_pts_ = pkt->data.frame.pts; - bits_in_last_frame_ = frame_size_in_bits; - ++frame_number_; } + virtual void EndPassHook(void) { - if (bits_total_) { - const double file_size_in_kb = bits_total_ / 1000.; // bits per kilobit - duration_ = (last_pts_ + 1) * timebase_; - file_datarate_ = file_size_in_kb / duration_; + for (int sl = 0; sl < number_spatial_layers_; ++sl) { + for (int tl = 0; tl < number_temporal_layers_; ++tl) { + const int layer = sl * number_temporal_layers_ + tl; + const double file_size_in_kb = bits_total_[layer] / 1000.; + duration_ = (last_pts_ + 1) * timebase_; + file_datarate_[layer] = file_size_in_kb / duration_; + } } } @@ -1292,13 +1357,11 @@ class DatarateOnePassCbrSvc unsigned int GetMismatchFrames() { return mismatch_nframes_; } vpx_codec_pts_t last_pts_; - int64_t bits_in_buffer_model_; + int64_t bits_in_buffer_model_[VPX_MAX_LAYERS]; double timebase_; - int frame_number_; - vpx_codec_pts_t first_drop_; - int64_t bits_total_; + int64_t bits_total_[VPX_MAX_LAYERS]; double duration_; - double file_datarate_; + double file_datarate_[VPX_MAX_LAYERS]; size_t bits_in_last_frame_; vpx_svc_extra_cfg_t svc_params_; int speed_setting_; @@ -1307,14 +1370,22 @@ class DatarateOnePassCbrSvc int denoiser_on_; int tune_content_; int base_speed_setting_; + int spatial_layer_id_; + int temporal_layer_id_; + int number_spatial_layers_; + int number_temporal_layers_; + int layer_target_avg_bandwidth_[VPX_MAX_LAYERS]; }; static void assign_layer_bitrates(vpx_codec_enc_cfg_t *const enc_cfg, const vpx_svc_extra_cfg_t *svc_params, int spatial_layers, int temporal_layers, - int temporal_layering_mode) { + int temporal_layering_mode, + int *layer_target_avg_bandwidth, + int64_t *bits_in_buffer_model) { int sl, spatial_layer_target; float total = 0; float alloc_ratio[VPX_MAX_LAYERS] = { 0 }; + float framerate = 30.0; for (sl = 0; sl < spatial_layers; ++sl) { if (svc_params->scaling_factor_den[sl] > 0) { alloc_ratio[sl] = (float)(svc_params->scaling_factor_num[sl] * 1.0 / @@ -1334,10 +1405,43 @@ static void assign_layer_bitrates(vpx_codec_enc_cfg_t *const enc_cfg, } else if (temporal_layering_mode == 2) { enc_cfg->layer_target_bitrate[index] = spatial_layer_target * 2 / 3; enc_cfg->layer_target_bitrate[index + 1] = spatial_layer_target; + } else if (temporal_layering_mode <= 1) { + enc_cfg->layer_target_bitrate[index] = spatial_layer_target; + } + } + for (sl = 0; sl < spatial_layers; ++sl) { + for (int tl = 0; tl < temporal_layers; ++tl) { + const int layer = sl * temporal_layers + tl; + float layer_framerate = framerate; + if (temporal_layers == 2 && tl == 0) layer_framerate = framerate / 2; + if (temporal_layers == 3 && tl == 0) layer_framerate = framerate / 4; + if (temporal_layers == 3 && tl == 1) layer_framerate = framerate / 2; + layer_target_avg_bandwidth[layer] = static_cast<int>( + enc_cfg->layer_target_bitrate[layer] * 1000.0 / layer_framerate); + bits_in_buffer_model[layer] = + enc_cfg->layer_target_bitrate[layer] * enc_cfg->rc_buf_initial_sz; } } } +static void CheckLayerRateTargeting(vpx_codec_enc_cfg_t *const cfg, + int number_spatial_layers, + int number_temporal_layers, + double *file_datarate, + double thresh_overshoot, + double thresh_undershoot) { + for (int sl = 0; sl < number_spatial_layers; ++sl) + for (int tl = 0; tl < number_temporal_layers; ++tl) { + const int layer = sl * number_temporal_layers + tl; + ASSERT_GE(cfg->layer_target_bitrate[layer], + file_datarate[layer] * thresh_overshoot) + << " The datarate for the file exceeds the target by too much!"; + ASSERT_LE(cfg->layer_target_bitrate[layer], + file_datarate[layer] * thresh_undershoot) + << " The datarate for the file is lower than the target by too much!"; + } +} + // 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. @@ -1361,14 +1465,19 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL1TLScreenContent1) { svc_params_.scaling_factor_den[1] = 288; cfg_.rc_dropframe_thresh = 10; cfg_.kf_max_dist = 9999; + number_spatial_layers_ = cfg_.ss_number_layers; + number_temporal_layers_ = cfg_.ts_number_layers; ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60); cfg_.rc_target_bitrate = 500; ResetModel(); tune_content_ = 1; base_speed_setting_ = speed_setting_; assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, - cfg_.ts_number_layers, cfg_.temporal_layering_mode); + cfg_.ts_number_layers, cfg_.temporal_layering_mode, + layer_target_avg_bandwidth_, bits_in_buffer_model_); ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + CheckLayerRateTargeting(&cfg_, number_spatial_layers_, + number_temporal_layers_, file_datarate_, 0.78, 1.15); EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames()); } @@ -1396,6 +1505,8 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL3TL) { svc_params_.scaling_factor_den[1] = 288; cfg_.rc_dropframe_thresh = 0; cfg_.kf_max_dist = 9999; + number_spatial_layers_ = cfg_.ss_number_layers; + number_temporal_layers_ = cfg_.ts_number_layers; ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1, 0, 400); // TODO(marpan): Check that effective_datarate for each layer hits the @@ -1404,12 +1515,12 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL3TL) { cfg_.rc_target_bitrate = i; ResetModel(); assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, - cfg_.ts_number_layers, cfg_.temporal_layering_mode); + cfg_.ts_number_layers, cfg_.temporal_layering_mode, + layer_target_avg_bandwidth_, bits_in_buffer_model_); ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); - ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.78) - << " 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!"; + CheckLayerRateTargeting(&cfg_, number_spatial_layers_, + number_temporal_layers_, file_datarate_, 0.78, + 1.15); #if CONFIG_VP9_DECODER // 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. @@ -1444,6 +1555,8 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL3TLDenoiserOn) { svc_params_.scaling_factor_den[1] = 288; cfg_.rc_dropframe_thresh = 0; cfg_.kf_max_dist = 9999; + number_spatial_layers_ = cfg_.ss_number_layers; + number_temporal_layers_ = cfg_.ts_number_layers; ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1, 0, 400); // TODO(marpan): Check that effective_datarate for each layer hits the @@ -1456,12 +1569,12 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL3TLDenoiserOn) { ResetModel(); denoiser_on_ = noise_sen; assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, - cfg_.ts_number_layers, cfg_.temporal_layering_mode); + cfg_.ts_number_layers, cfg_.temporal_layering_mode, + layer_target_avg_bandwidth_, bits_in_buffer_model_); ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); - ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.78) - << " 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!"; + CheckLayerRateTargeting(&cfg_, number_spatial_layers_, + number_temporal_layers_, file_datarate_, 0.78, + 1.15); #if CONFIG_VP9_DECODER // Number of temporal layers > 1, so half of the frames in this SVC // pattern @@ -1476,7 +1589,7 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL3TLDenoiserOn) { // 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, DISABLED_OnePassCbrSvc2SL3TLSmallKf) { +TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL3TLSmallKf) { cfg_.rc_buf_initial_sz = 500; cfg_.rc_buf_optimal_sz = 500; cfg_.rc_buf_sz = 1000; @@ -1498,6 +1611,8 @@ TEST_P(DatarateOnePassCbrSvc, DISABLED_OnePassCbrSvc2SL3TLSmallKf) { svc_params_.scaling_factor_den[1] = 288; cfg_.rc_dropframe_thresh = 10; cfg_.rc_target_bitrate = 400; + number_spatial_layers_ = cfg_.ss_number_layers; + number_temporal_layers_ = cfg_.ts_number_layers; ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1, 0, 400); // For this 3 temporal layer case, pattern repeats every 4 frames, so choose @@ -1506,12 +1621,12 @@ TEST_P(DatarateOnePassCbrSvc, DISABLED_OnePassCbrSvc2SL3TLSmallKf) { cfg_.kf_max_dist = j; ResetModel(); assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, - cfg_.ts_number_layers, cfg_.temporal_layering_mode); + cfg_.ts_number_layers, cfg_.temporal_layering_mode, + layer_target_avg_bandwidth_, bits_in_buffer_model_); ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); - ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.80) - << " 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!"; + CheckLayerRateTargeting(&cfg_, number_spatial_layers_, + number_temporal_layers_, file_datarate_, 0.78, + 1.15); } } @@ -1539,16 +1654,17 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL3TL4Threads) { svc_params_.scaling_factor_den[1] = 288; cfg_.rc_dropframe_thresh = 0; cfg_.kf_max_dist = 9999; + number_spatial_layers_ = cfg_.ss_number_layers; + number_temporal_layers_ = cfg_.ts_number_layers; ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60); cfg_.rc_target_bitrate = 800; ResetModel(); assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, - cfg_.ts_number_layers, cfg_.temporal_layering_mode); + cfg_.ts_number_layers, cfg_.temporal_layering_mode, + layer_target_avg_bandwidth_, bits_in_buffer_model_); ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); - ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.78) - << " 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!"; + CheckLayerRateTargeting(&cfg_, number_spatial_layers_, + number_temporal_layers_, file_datarate_, 0.78, 1.15); #if CONFIG_VP9_DECODER // 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. @@ -1584,17 +1700,18 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SL3TL) { svc_params_.scaling_factor_den[2] = 288; cfg_.rc_dropframe_thresh = 0; cfg_.kf_max_dist = 9999; + number_spatial_layers_ = cfg_.ss_number_layers; + number_temporal_layers_ = cfg_.ts_number_layers; ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1, 0, 400); cfg_.rc_target_bitrate = 800; ResetModel(); assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, - cfg_.ts_number_layers, cfg_.temporal_layering_mode); + cfg_.ts_number_layers, cfg_.temporal_layering_mode, + layer_target_avg_bandwidth_, bits_in_buffer_model_); ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); - ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.78) - << " 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!"; + CheckLayerRateTargeting(&cfg_, number_spatial_layers_, + number_temporal_layers_, file_datarate_, 0.78, 1.15); #if CONFIG_VP9_DECODER // 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. @@ -1630,6 +1747,8 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SL3TLSmallKf) { svc_params_.scaling_factor_den[2] = 288; cfg_.rc_dropframe_thresh = 10; cfg_.rc_target_bitrate = 800; + number_spatial_layers_ = cfg_.ss_number_layers; + number_temporal_layers_ = cfg_.ts_number_layers; ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1, 0, 400); // For this 3 temporal layer case, pattern repeats every 4 frames, so choose @@ -1638,12 +1757,12 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SL3TLSmallKf) { cfg_.kf_max_dist = j; ResetModel(); assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, - cfg_.ts_number_layers, cfg_.temporal_layering_mode); + cfg_.ts_number_layers, cfg_.temporal_layering_mode, + layer_target_avg_bandwidth_, bits_in_buffer_model_); ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); - ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.80) - << " 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!"; + CheckLayerRateTargeting(&cfg_, number_spatial_layers_, + number_temporal_layers_, file_datarate_, 0.78, + 1.15); } } @@ -1673,16 +1792,17 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SL3TL4threads) { svc_params_.scaling_factor_den[2] = 288; cfg_.rc_dropframe_thresh = 0; cfg_.kf_max_dist = 9999; + number_spatial_layers_ = cfg_.ss_number_layers; + number_temporal_layers_ = cfg_.ts_number_layers; ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60); cfg_.rc_target_bitrate = 800; ResetModel(); assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, - cfg_.ts_number_layers, cfg_.temporal_layering_mode); + cfg_.ts_number_layers, cfg_.temporal_layering_mode, + layer_target_avg_bandwidth_, bits_in_buffer_model_); ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); - ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.78) - << " 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!"; + CheckLayerRateTargeting(&cfg_, number_spatial_layers_, + number_temporal_layers_, file_datarate_, 0.78, 1.15); #if CONFIG_VP9_DECODER // 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. @@ -1720,9 +1840,19 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SL1TL5x5MultipleRuns) { cfg_.layer_target_bitrate[0] = 300; cfg_.layer_target_bitrate[1] = 1400; cfg_.rc_target_bitrate = 1700; - ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60); + number_spatial_layers_ = cfg_.ss_number_layers; + number_temporal_layers_ = cfg_.ts_number_layers; ResetModel(); + layer_target_avg_bandwidth_[0] = cfg_.layer_target_bitrate[0] * 1000 / 30; + bits_in_buffer_model_[0] = + cfg_.layer_target_bitrate[0] * cfg_.rc_buf_initial_sz; + layer_target_avg_bandwidth_[1] = cfg_.layer_target_bitrate[1] * 1000 / 30; + bits_in_buffer_model_[1] = + cfg_.layer_target_bitrate[1] * cfg_.rc_buf_initial_sz; + ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60); ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + CheckLayerRateTargeting(&cfg_, number_spatial_layers_, + number_temporal_layers_, file_datarate_, 0.78, 1.15); EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames()); } diff --git a/test/encode_test_driver.cc b/test/encode_test_driver.cc index 5d2b4008a..b2cbc3f05 100644 --- a/test/encode_test_driver.cc +++ b/test/encode_test_driver.cc @@ -201,6 +201,8 @@ void EncoderTest::RunLoop(VideoSource *video) { PreEncodeFrameHook(video, encoder.get()); encoder->EncodeFrame(video, frame_flags_); + PostEncodeFrameHook(encoder.get()); + CxDataIterator iter = encoder->GetCxData(); bool has_cxdata = false; diff --git a/test/encode_test_driver.h b/test/encode_test_driver.h index 1b4a5a671..89a3b1767 100644 --- a/test/encode_test_driver.h +++ b/test/encode_test_driver.h @@ -219,6 +219,8 @@ class EncoderTest { virtual void PreEncodeFrameHook(VideoSource * /*video*/, Encoder * /*encoder*/) {} + virtual void PostEncodeFrameHook(Encoder * /*encoder*/) {} + // Hook to be called on every compressed data packet. virtual void FramePktHook(const vpx_codec_cx_pkt_t * /*pkt*/) {} |