This commit is contained in:
Mike Jerris
2016-09-26 14:31:51 -04:00
parent 2b1f0da5c4
commit 8c5f0301f3
1008 changed files with 110177 additions and 201326 deletions

View File

@@ -18,8 +18,9 @@
namespace {
class DatarateTestLarge : public ::libvpx_test::EncoderTest,
public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
class DatarateTestLarge
: public ::libvpx_test::EncoderTest,
public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
public:
DatarateTestLarge() : EncoderTest(GET_PARAM(0)) {}
@@ -45,8 +46,9 @@ class DatarateTestLarge : public ::libvpx_test::EncoderTest,
virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
::libvpx_test::Encoder *encoder) {
if (video->frame() == 0)
if (video->frame() == 0) {
encoder->Control(VP8E_SET_NOISE_SENSITIVITY, denoiser_on_);
}
if (denoiser_offon_test_) {
ASSERT_GT(denoiser_offon_period_, 0)
@@ -71,8 +73,7 @@ class DatarateTestLarge : public ::libvpx_test::EncoderTest,
// http://code.google.com/p/webm/issues/detail?id=496 is fixed.
// For now the codec assumes buffer starts at starting buffer rate
// plus one frame's time.
if (last_pts_ == 0)
duration = 1;
if (last_pts_ == 0) duration = 1;
// Add to the buffer the bits we'd expect from a constant bitrate server.
bits_in_buffer_model_ += static_cast<int64_t>(
@@ -83,14 +84,14 @@ class DatarateTestLarge : public ::libvpx_test::EncoderTest,
* empty - and then stop showing frames until we've got enough bits to
* show one. As noted in comment below (issue 495), this does not currently
* apply to key frames. For now exclude key frames in condition below. */
const bool key_frame = (pkt->data.frame.flags & VPX_FRAME_IS_KEY)
? true: false;
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;
<< pkt->data.frame.pts;
}
const size_t frame_size_in_bits = pkt->data.frame.sz * 8;
const int64_t frame_size_in_bits = pkt->data.frame.sz * 8;
// Subtract from the buffer the bits associated with a played back frame.
bits_in_buffer_model_ -= frame_size_in_bits;
@@ -99,8 +100,7 @@ class DatarateTestLarge : public ::libvpx_test::EncoderTest,
bits_total_ += frame_size_in_bits;
// If first drop not set and we have a drop set it to this time.
if (!first_drop_ && duration > 1)
first_drop_ = last_pts_ + 1;
if (!first_drop_ && duration > 1) first_drop_ = last_pts_ + 1;
// Update the most recent pts.
last_pts_ = pkt->data.frame.pts;
@@ -119,8 +119,8 @@ class DatarateTestLarge : public ::libvpx_test::EncoderTest,
duration_ = (last_pts_ + 1) * timebase_;
// Effective file datarate includes the time spent prebuffering.
effective_datarate_ = (bits_total_ - bits_in_last_frame_) / 1000.0
/ (cfg_.rc_buf_initial_sz / 1000.0 + duration_);
effective_datarate_ = (bits_total_ - bits_in_last_frame_) / 1000.0 /
(cfg_.rc_buf_initial_sz / 1000.0 + duration_);
file_datarate_ = file_size_in_kb / duration_;
}
@@ -135,7 +135,7 @@ class DatarateTestLarge : public ::libvpx_test::EncoderTest,
double duration_;
double file_datarate_;
double effective_datarate_;
size_t bits_in_last_frame_;
int64_t bits_in_last_frame_;
int denoiser_on_;
int denoiser_offon_test_;
int denoiser_offon_period_;
@@ -256,8 +256,39 @@ TEST_P(DatarateTestLarge, ChangingDropFrameThresh) {
}
}
class DatarateTestVP9Large : public ::libvpx_test::EncoderTest,
public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
// Disabled for tsan, see:
// https://bugs.chromium.org/p/webm/issues/detail?id=1049
#if defined(__has_feature)
#if __has_feature(thread_sanitizer)
#define BUILDING_WITH_TSAN
#endif
#endif
#ifndef BUILDING_WITH_TSAN
TEST_P(DatarateTestLarge, DropFramesMultiThreads) {
denoiser_on_ = 0;
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_dropframe_thresh = 30;
cfg_.rc_max_quantizer = 56;
cfg_.rc_end_usage = VPX_CBR;
// Encode using multiple threads.
cfg_.g_threads = 2;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 140);
cfg_.rc_target_bitrate = 200;
ResetModel();
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
<< " The datarate for the file exceeds the target!";
ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.3)
<< " The datarate for the file missed the target!";
}
#endif
class DatarateTestVP9Large
: public ::libvpx_test::EncoderTest,
public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
public:
DatarateTestVP9Large() : EncoderTest(GET_PARAM(0)) {}
@@ -307,8 +338,8 @@ class DatarateTestVP9Large : public ::libvpx_test::EncoderTest,
if (num_temp_layers == 2) {
if (frame_num % 2 == 0) {
// Layer 0: predict from L and ARF, update L.
frame_flags = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF |
VP8_EFLAG_NO_UPD_ARF;
frame_flags =
VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
} else {
// Layer 1: predict from L, G and ARF, and update G.
frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
@@ -317,15 +348,15 @@ class DatarateTestVP9Large : public ::libvpx_test::EncoderTest,
} else if (num_temp_layers == 3) {
if (frame_num % 4 == 0) {
// Layer 0: predict from L and ARF; update L.
frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
VP8_EFLAG_NO_REF_GF;
frame_flags =
VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF;
} else if ((frame_num - 2) % 4 == 0) {
// Layer 1: predict from L, G, ARF; update G.
frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
} else if ((frame_num - 1) % 2 == 0) {
} else if ((frame_num - 1) % 2 == 0) {
// Layer 2: predict from L, G, ARF; update none.
frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
VP8_EFLAG_NO_UPD_LAST;
frame_flags =
VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
}
}
return frame_flags;
@@ -353,8 +384,7 @@ class DatarateTestVP9Large : public ::libvpx_test::EncoderTest,
virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
::libvpx_test::Encoder *encoder) {
if (video->frame() == 0)
encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
if (video->frame() == 0) encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
if (denoiser_offon_test_) {
ASSERT_GT(denoiser_offon_period_, 0)
@@ -374,8 +404,8 @@ class DatarateTestVP9Large : public ::libvpx_test::EncoderTest,
vpx_svc_layer_id_t layer_id;
layer_id.spatial_layer_id = 0;
frame_flags_ = SetFrameFlags(video->frame(), cfg_.ts_number_layers);
layer_id.temporal_layer_id = SetLayerId(video->frame(),
cfg_.ts_number_layers);
layer_id.temporal_layer_id =
SetLayerId(video->frame(), cfg_.ts_number_layers);
encoder->Control(VP9E_SET_SVC_LAYER_ID, &layer_id);
}
const vpx_rational_t tb = video->timebase();
@@ -383,15 +413,13 @@ class DatarateTestVP9Large : public ::libvpx_test::EncoderTest,
duration_ = 0;
}
virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
// Time since last timestamp = duration.
vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
if (duration > 1) {
// If first drop not set and we have a drop set it to this time.
if (!first_drop_)
first_drop_ = last_pts_ + 1;
if (!first_drop_) first_drop_ = last_pts_ + 1;
// Update the number of frame drops.
num_drops_ += static_cast<int>(duration - 1);
// Update counter for total number of frames (#frames input to encoder).
@@ -407,7 +435,7 @@ class DatarateTestVP9Large : public ::libvpx_test::EncoderTest,
// Buffer should not go negative.
ASSERT_GE(bits_in_buffer_model_, 0) << "Buffer Underrun at frame "
<< pkt->data.frame.pts;
<< pkt->data.frame.pts;
const size_t frame_size_in_bits = pkt->data.frame.sz * 8;
@@ -425,7 +453,7 @@ class DatarateTestVP9Large : public ::libvpx_test::EncoderTest,
virtual void EndPassHook(void) {
for (int layer = 0; layer < static_cast<int>(cfg_.ts_number_layers);
++layer) {
++layer) {
duration_ = (last_pts_ + 1) * timebase_;
if (bits_total_[layer]) {
// Effective file datarate:
@@ -450,7 +478,55 @@ class DatarateTestVP9Large : public ::libvpx_test::EncoderTest,
int denoiser_offon_period_;
};
// Check basic rate targeting,
// Check basic rate targeting for VBR mode with 0 lag.
TEST_P(DatarateTestVP9Large, BasicRateTargetingVBRLagZero) {
cfg_.rc_min_quantizer = 0;
cfg_.rc_max_quantizer = 63;
cfg_.g_error_resilient = 0;
cfg_.rc_end_usage = VPX_VBR;
cfg_.g_lag_in_frames = 0;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 300);
for (int i = 400; i <= 800; i += 400) {
cfg_.rc_target_bitrate = i;
ResetModel();
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.75)
<< " The datarate for the file is lower than target by too much!";
ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.25)
<< " The datarate for the file is greater than target by too much!";
}
}
// Check basic rate targeting for VBR mode with non-zero lag.
TEST_P(DatarateTestVP9Large, BasicRateTargetingVBRLagNonZero) {
cfg_.rc_min_quantizer = 0;
cfg_.rc_max_quantizer = 63;
cfg_.g_error_resilient = 0;
cfg_.rc_end_usage = VPX_VBR;
// For non-zero lag, rate control will work (be within bounds) for
// real-time mode.
if (deadline_ == VPX_DL_REALTIME) {
cfg_.g_lag_in_frames = 15;
} else {
cfg_.g_lag_in_frames = 0;
}
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 300);
for (int i = 400; i <= 800; i += 400) {
cfg_.rc_target_bitrate = i;
ResetModel();
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.75)
<< " The datarate for the file is lower than target by too much!";
ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.25)
<< " The datarate for the file is greater than target by too much!";
}
}
// Check basic rate targeting for CBR mode.
TEST_P(DatarateTestVP9Large, BasicRateTargeting) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
@@ -474,7 +550,31 @@ TEST_P(DatarateTestVP9Large, BasicRateTargeting) {
}
}
// Check basic rate targeting,
// Check basic rate targeting for CBR mode, with 2 threads and dropped frames.
TEST_P(DatarateTestVP9Large, BasicRateTargetingDropFramesMultiThreads) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
cfg_.rc_dropframe_thresh = 30;
cfg_.rc_min_quantizer = 0;
cfg_.rc_max_quantizer = 63;
cfg_.rc_end_usage = VPX_CBR;
cfg_.g_lag_in_frames = 0;
// Encode using multiple threads.
cfg_.g_threads = 2;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 140);
cfg_.rc_target_bitrate = 200;
ResetModel();
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
<< " The datarate for the file is lower than target by too much!";
ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
<< " The datarate for the file is greater than target by too much!";
}
// Check basic rate targeting for CBR.
TEST_P(DatarateTestVP9Large, BasicRateTargeting444) {
::libvpx_test::Y4mVideoSource video("rush_hour_444.y4m", 0, 140);
@@ -499,7 +599,7 @@ TEST_P(DatarateTestVP9Large, BasicRateTargeting444) {
ASSERT_LE(static_cast<double>(cfg_.rc_target_bitrate),
effective_datarate_[0] * 1.15)
<< " The datarate for the file missed the target!"
<< cfg_.rc_target_bitrate << " "<< effective_datarate_;
<< cfg_.rc_target_bitrate << " " << effective_datarate_;
}
}
@@ -519,6 +619,9 @@ TEST_P(DatarateTestVP9Large, ChangingDropFrameThresh) {
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);
@@ -566,8 +669,7 @@ TEST_P(DatarateTestVP9Large, BasicRateTargeting2TemporalLayers) {
cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
if (deadline_ == VPX_DL_REALTIME)
cfg_.g_error_resilient = 1;
if (deadline_ == VPX_DL_REALTIME) cfg_.g_error_resilient = 1;
::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 200);
@@ -581,10 +683,12 @@ TEST_P(DatarateTestVP9Large, BasicRateTargeting2TemporalLayers) {
for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.85)
<< " The datarate for the file is lower than target by too much, "
"for layer: " << j;
"for layer: "
<< j;
ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.15)
<< " The datarate for the file is greater than target by too much, "
"for layer: " << j;
"for layer: "
<< j;
}
}
}
@@ -624,12 +728,14 @@ TEST_P(DatarateTestVP9Large, BasicRateTargeting3TemporalLayers) {
// Adjust the thresholds to be tighter than .75.
ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.75)
<< " The datarate for the file is lower than target by too much, "
"for layer: " << j;
"for layer: "
<< j;
// TODO(yaowu): Work out more stable rc control strategy and
// Adjust the thresholds to be tighter than 1.25.
ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.25)
<< " The datarate for the file is greater than target by too much, "
"for layer: " << j;
"for layer: "
<< j;
}
}
}
@@ -669,10 +775,12 @@ TEST_P(DatarateTestVP9Large, BasicRateTargeting3TemporalLayersFrameDropping) {
for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.85)
<< " The datarate for the file is lower than target by too much, "
"for layer: " << j;
"for layer: "
<< j;
ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.15)
<< " The datarate for the file is greater than target by too much, "
"for layer: " << j;
"for layer: "
<< j;
// Expect some frame drops in this test: for this 200 frames test,
// expect at least 10% and not more than 60% drops.
ASSERT_GE(num_drops_, 20);
@@ -742,11 +850,15 @@ TEST_P(DatarateTestVP9Large, DenoiserOffOn) {
}
#endif // CONFIG_VP9_TEMPORAL_DENOISING
class DatarateOnePassCbrSvc : public ::libvpx_test::EncoderTest,
public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
class DatarateOnePassCbrSvc
: public ::libvpx_test::EncoderTest,
public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
public:
DatarateOnePassCbrSvc() : EncoderTest(GET_PARAM(0)) {}
DatarateOnePassCbrSvc() : EncoderTest(GET_PARAM(0)) {
memset(&svc_params_, 0, sizeof(svc_params_));
}
virtual ~DatarateOnePassCbrSvc() {}
protected:
virtual void SetUp() {
InitializeConfig();
@@ -764,8 +876,7 @@ class DatarateOnePassCbrSvc : public ::libvpx_test::EncoderTest,
mismatch_psnr_ = 0.0;
mismatch_nframes_ = 0;
}
virtual void BeginPassHook(unsigned int /*pass*/) {
}
virtual void BeginPassHook(unsigned int /*pass*/) {}
virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
::libvpx_test::Encoder *encoder) {
if (video->frame() == 0) {
@@ -774,10 +885,10 @@ class DatarateOnePassCbrSvc : public ::libvpx_test::EncoderTest,
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;
svc_params_.speed_per_layer[0] = 5;
for (i = 1; i < VPX_SS_MAX_LAYERS; ++i) {
svc_params_.speed_per_layer[i] = 7;
}
encoder->Control(VP9E_SET_SVC, 1);
encoder->Control(VP9E_SET_SVC_PARAMETERS, &svc_params_);
encoder->Control(VP8E_SET_CPUUSED, speed_setting_);
@@ -791,21 +902,19 @@ class DatarateOnePassCbrSvc : public ::libvpx_test::EncoderTest,
}
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;
if (last_pts_ == 0) duration = 1;
bits_in_buffer_model_ += static_cast<int64_t>(
duration * timebase_ * cfg_.rc_target_bitrate * 1000);
const bool key_frame = (pkt->data.frame.flags & VPX_FRAME_IS_KEY)
? true: false;
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;
<< pkt->data.frame.pts;
}
const size_t frame_size_in_bits = pkt->data.frame.sz * 8;
bits_in_buffer_model_ -= frame_size_in_bits;
bits_total_ += frame_size_in_bits;
if (!first_drop_ && duration > 1)
first_drop_ = last_pts_ + 1;
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_;
@@ -814,22 +923,17 @@ class DatarateOnePassCbrSvc : public ::libvpx_test::EncoderTest,
if (bits_total_) {
const double file_size_in_kb = bits_total_ / 1000.; // bits per kilobit
duration_ = (last_pts_ + 1) * timebase_;
effective_datarate_ = (bits_total_ - bits_in_last_frame_) / 1000.0
/ (cfg_.rc_buf_initial_sz / 1000.0 + duration_);
file_datarate_ = file_size_in_kb / duration_;
}
}
virtual void MismatchHook(const vpx_image_t *img1,
const vpx_image_t *img2) {
virtual void MismatchHook(const vpx_image_t *img1, const vpx_image_t *img2) {
double mismatch_psnr = compute_psnr(img1, img2);
mismatch_psnr_ += mismatch_psnr;
++mismatch_nframes_;
}
unsigned int GetMismatchFrames() {
return mismatch_nframes_;
}
unsigned int GetMismatchFrames() { return mismatch_nframes_; }
vpx_codec_pts_t last_pts_;
int64_t bits_in_buffer_model_;
@@ -839,7 +943,6 @@ class DatarateOnePassCbrSvc : public ::libvpx_test::EncoderTest,
int64_t bits_total_;
double duration_;
double file_datarate_;
double effective_datarate_;
size_t bits_in_last_frame_;
vpx_svc_extra_cfg_t svc_params_;
int speed_setting_;
@@ -847,44 +950,80 @@ class DatarateOnePassCbrSvc : public ::libvpx_test::EncoderTest,
int mismatch_nframes_;
};
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) {
const vpx_svc_extra_cfg_t *svc_params,
int spatial_layers, int temporal_layers,
int temporal_layering_mode) {
int sl, spatial_layer_target;
float total = 0;
float alloc_ratio[VPX_MAX_LAYERS] = {0};
float alloc_ratio[VPX_MAX_LAYERS] = { 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 / svc_params->scaling_factor_den[sl]);
alloc_ratio[sl] = (float)(svc_params->scaling_factor_num[sl] * 1.0 /
svc_params->scaling_factor_den[sl]);
total += alloc_ratio[sl];
}
}
for (sl = 0; sl < spatial_layers; ++sl) {
enc_cfg->ss_target_bitrate[sl] = spatial_layer_target =
(unsigned int)(enc_cfg->rc_target_bitrate *
alloc_ratio[sl] / total);
(unsigned int)(enc_cfg->rc_target_bitrate * alloc_ratio[sl] / total);
const int index = sl * temporal_layers;
if (temporal_layering_mode == 3) {
enc_cfg->layer_target_bitrate[index] =
spatial_layer_target >> 1;
enc_cfg->layer_target_bitrate[index] = spatial_layer_target >> 1;
enc_cfg->layer_target_bitrate[index + 1] =
(spatial_layer_target >> 1) + (spatial_layer_target >> 2);
enc_cfg->layer_target_bitrate[index + 2] =
spatial_layer_target;
enc_cfg->layer_target_bitrate[index + 2] = spatial_layer_target;
} 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;
enc_cfg->layer_target_bitrate[index] = spatial_layer_target * 2 / 3;
enc_cfg->layer_target_bitrate[index + 1] = spatial_layer_target;
}
}
}
// 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;
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 = 2;
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] = 144;
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_.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
// layer target_bitrate.
for (int i = 200; i <= 800; i += 200) {
cfg_.rc_target_bitrate = i;
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, file_datarate_ * 0.85)
<< " 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 CIF clip with 1 thread, and few short key frame periods.
TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayersSmallKf) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
@@ -907,25 +1046,26 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc) {
cfg_.rc_dropframe_thresh = 10;
::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
// layer target_bitrate. Also check if test can pass at lower bitrate (~200k).
for (int i = 400; i <= 800; i += 200) {
cfg_.rc_target_bitrate = i;
cfg_.rc_target_bitrate = 400;
// For this 3 temporal layer case, pattern repeats every 4 frames, so choose
// 4 key neighboring key frame periods (so key frame will land on 0-2-1-2).
for (int j = 64; j <= 67; j++) {
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);
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_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85)
<< " 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(GetMismatchFrames(), (unsigned int) 0);
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, OnePassCbrSvc4threads) {
TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayers4threads) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
@@ -946,26 +1086,151 @@ TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc4threads) {
svc_params_.scaling_factor_num[1] = 288;
svc_params_.scaling_factor_den[1] = 288;
cfg_.rc_dropframe_thresh = 10;
::libvpx_test::I420VideoSource video("niklas_1280_720_30.y4m", 1280, 720,
30, 1, 0, 300);
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);
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_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85)
<< " 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(GetMismatchFrames(), (unsigned int) 0);
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 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, file_datarate_ * 0.85)
<< " 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());
}
// 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) {
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;
::libvpx_test::I420VideoSource video("niklas_1280_720_30.y4m", 1280, 720, 30,
1, 0, 300);
cfg_.rc_target_bitrate = 800;
// For this 3 temporal layer case, pattern repeats every 4 frames, so choose
// 4 key neighboring key frame periods (so key frame will land on 0-2-1-2).
for (int j = 32; j <= 35; j++) {
cfg_.kf_max_dist = j;
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, file_datarate_ * 0.85)
<< " 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) {
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, file_datarate_ * 0.85)
<< " 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());
}
VP8_INSTANTIATE_TEST_CASE(DatarateTestLarge, ALL_TEST_MODES);
VP9_INSTANTIATE_TEST_CASE(DatarateTestVP9Large,
::testing::Values(::libvpx_test::kOnePassGood,
::libvpx_test::kRealTime),
::testing::Range(2, 7));
::testing::Range(2, 9));
VP9_INSTANTIATE_TEST_CASE(DatarateOnePassCbrSvc,
::testing::Values(::libvpx_test::kRealTime),
::testing::Range(5, 8));
::testing::Range(5, 9));
} // namespace