Updates to videoprocessor_integration test:
-added metric for expected key frame size mismatch
-fix to start bitrate
-updates to some expected values in tests
Review URL: https://webrtc-codereview.appspot.com/641007
git-svn-id: http://webrtc.googlecode.com/svn/trunk@2404 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/src/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc b/src/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc
index 6707cd4..febc37d 100644
--- a/src/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc
+++ b/src/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc
@@ -27,6 +27,13 @@
namespace webrtc {
+// Maximum number of rate updates (i.e., calls to encoder to change bitrate
+// and/or frame rate) for the current tests.
+const int kMaxNumRateUpdates = 3;
+
+const int kPercTargetvsActualMismatch = 20;
+
+// Codec and network settings.
struct CodecConfigPars {
float packet_loss;
int num_temporal_layers;
@@ -35,14 +42,49 @@
bool denoising_on;
};
+// Quality metrics.
+struct QualityMetrics {
+ double minimum_avg_psnr;
+ double minimum_min_psnr;
+ double minimum_avg_ssim;
+ double minimum_min_ssim;
+};
+
+// The sequence of bitrate and frame rate changes for the encoder, the frame
+// number where the changes are made, and the total number of frames for the
+// test.
+struct RateProfile {
+ int target_bit_rate[kMaxNumRateUpdates];
+ int input_frame_rate[kMaxNumRateUpdates];
+ int frame_index_rate_update[kMaxNumRateUpdates + 1];
+ int num_frames;
+};
+
+// Metrics for the rate control. The rate mismatch metrics are defined as
+// percentages.|max_time_hit_target| is defined as number of frames, after a
+// rate update is made to the encoder, for the encoder to reach within
+// |kPercTargetvsActualMismatch| of new target rate. The metrics are defined for
+// each rate update sequence.
+struct RateControlMetrics {
+ int max_num_dropped_frames;
+ int max_key_frame_size_mismatch;
+ int max_delta_frame_size_mismatch;
+ int max_encoding_rate_mismatch;
+ int max_time_hit_target;
+ int num_spatial_resizes;
+};
+
+
// Sequence used is foreman (CIF): may be better to use VGA for resize test.
const int kCIFWidth = 352;
const int kCIFHeight = 288;
-const int kFrameRate = 30;
-const int kStartBitRateKbps = 300;
const int kNbrFramesShort = 100; // Some tests are run for shorter sequence.
const int kNbrFramesLong = 299;
-const int kPercTargetvsActualMismatch = 20;
+
+// Parameters from VP8 wrapper, which control target size of key frames.
+const float kInitialBufferSize = 0.5f;
+const float kOptimalBufferSize = 0.6f;
+const float kScaleKeyFrameSize = 0.5f;
// Integration test for video processor. Encodes+decodes a clip and
// writes it to the output directory. After completion, quality metrics
@@ -83,6 +125,11 @@
int bit_rate_;
int frame_rate_;
int layer_;
+ float target_size_key_frame_initial_;
+ float target_size_key_frame_;
+ float sum_key_frame_size_mismatch_;
+ int num_key_frames_;
+ float start_bitrate_;
// Codec and network settings.
float packet_loss_;
@@ -116,7 +163,7 @@
// Get a codec configuration struct and configure it.
VideoCodingModule::Codec(kVideoCodecVP8, &codec_settings_);
config_.codec_settings = &codec_settings_;
- config_.codec_settings->startBitrate = kStartBitRateKbps;
+ config_.codec_settings->startBitrate = start_bitrate_;
config_.codec_settings->width = kCIFWidth;
config_.codec_settings->height = kCIFHeight;
// These features may be set depending on the test.
@@ -158,28 +205,41 @@
per_frame_bandwidth_[i] = static_cast<float>(bit_rate_layer_[i]) /
static_cast<float>(frame_rate_layer_[i]);
}
+ // Set maximum size of key frames, following setting in the VP8 wrapper.
+ float max_key_size = kScaleKeyFrameSize * kOptimalBufferSize * frame_rate_;
+ // We don't know exact target size of the key frames (except for first one),
+ // but the minimum in libvpx is ~|3 * per_frame_bandwidth| and maximum is
+ // set by |max_key_size_ * per_frame_bandwidth|. Take middle point/average
+ // as reference for mismatch. Note key frames always correspond to base
+ // layer frame in this test.
+ target_size_key_frame_ = 0.5 * (3 + max_key_size) * per_frame_bandwidth_[0];
num_frames_total_ = 0;
sum_encoded_frame_size_total_ = 0.0f;
encoding_bitrate_total_ = 0.0f;
perc_encoding_rate_mismatch_ = 0.0f;
num_frames_to_hit_target_ = num_frames;
encoding_rate_within_target_ = false;
+ sum_key_frame_size_mismatch_ = 0.0;
+ num_key_frames_ = 0;
}
// For every encoded frame, update the rate control metrics.
- void UpdateRateControlMetrics(int frame_num,
- int max_encoding_rate_mismatch) {
+ void UpdateRateControlMetrics(int frame_num, VideoFrameType frame_type) {
int encoded_frame_size = processor_->EncodedFrameSize();
float encoded_size_kbits = encoded_frame_size * 8.0f / 1000.0f;
// Update layer data.
- // Ignore first frame (key frame), and any other key frames in the run,
- // for rate mismatch relative to per-frame bandwidth.
- // Note |frame_num| = 1 for the first frame in the run.
- if (frame_num > 1 && ((frame_num - 1) % key_frame_interval_ != 0 ||
- key_frame_interval_ < 0)) {
+ // Update rate mismatch relative to per-frame bandwidth for delta frames.
+ if (frame_type == kDeltaFrame) {
+ // TODO(marpan): Should we count dropped (zero size) frames in mismatch?
sum_frame_size_mismatch_[layer_] += fabs(encoded_size_kbits -
per_frame_bandwidth_[layer_]) /
per_frame_bandwidth_[layer_];
+ } else {
+ float target_size = (frame_num == 1) ? target_size_key_frame_initial_ :
+ target_size_key_frame_;
+ sum_key_frame_size_mismatch_ += fabs(encoded_size_kbits - target_size) /
+ target_size;
+ num_key_frames_ += 1;
}
sum_encoded_frame_size_[layer_] += encoded_size_kbits;
// Encoding bitrate per layer: from the start of the update/run to the
@@ -202,7 +262,8 @@
// Verify expected behavior of rate control and print out data.
void VerifyRateControl(int update_index,
- int max_frame_size_mismatch,
+ int max_key_frame_size_mismatch,
+ int max_delta_frame_size_mismatch,
int max_encoding_rate_mismatch,
int max_time_hit_target,
int max_num_dropped_frames,
@@ -219,6 +280,14 @@
" Number of spatial resizes = %d, \n",
num_frames_to_hit_target_, num_dropped_frames, num_resize_actions);
EXPECT_LE(perc_encoding_rate_mismatch_, max_encoding_rate_mismatch);
+ if (num_key_frames_ > 0) {
+ int perc_key_frame_size_mismatch = 100 * sum_key_frame_size_mismatch_ /
+ num_key_frames_;
+ printf(" Number of Key frames: %d \n"
+ " Key frame rate mismatch: %d \n",
+ num_key_frames_, perc_key_frame_size_mismatch);
+ EXPECT_LE(perc_key_frame_size_mismatch, max_key_frame_size_mismatch);
+ }
printf("\n");
printf("Rates statistics for Layer data \n");
for (int i = 0; i < num_temporal_layers_ ; i++) {
@@ -238,7 +307,7 @@
bit_rate_layer_[i], frame_rate_layer_[i], per_frame_bandwidth_[i],
encoding_bitrate_[i], perc_frame_size_mismatch,
perc_encoding_rate_mismatch, num_frames_per_update_[i]);
- EXPECT_LE(perc_frame_size_mismatch, max_frame_size_mismatch);
+ EXPECT_LE(perc_frame_size_mismatch, max_delta_frame_size_mismatch);
EXPECT_LE(perc_encoding_rate_mismatch, max_encoding_rate_mismatch);
}
printf("\n");
@@ -300,6 +369,15 @@
}
}
+ VideoFrameType FrameType(int frame_number) {
+ if (frame_number == 0 || ((frame_number) % key_frame_interval_ == 0 &&
+ key_frame_interval_ > 0)) {
+ return kKeyFrame;
+ } else {
+ return kDeltaFrame;
+ }
+ }
+
void TearDown() {
delete processor_;
delete packet_manipulator_;
@@ -310,21 +388,12 @@
}
// Processes all frames in the clip and verifies the result.
- void ProcessFramesAndVerify(double minimum_avg_psnr,
- double minimum_min_psnr,
- double minimum_avg_ssim,
- double minimum_min_ssim,
- int* target_bit_rate,
- int* input_frame_rate,
- int* frame_index_rate_update,
- int num_frames,
+ void ProcessFramesAndVerify(QualityMetrics quality_metrics,
+ RateProfile rate_profile,
CodecConfigPars process,
- int* max_frame_size_mismatch,
- int* max_encoding_rate_mismatch,
- int* max_time_hit_target,
- int* max_num_dropped_frames,
- int* num_spatial_resizes) {
+ RateControlMetrics* rc_metrics) {
// Codec/config settings.
+ start_bitrate_ = rate_profile.target_bit_rate[0];
packet_loss_ = process.packet_loss;
key_frame_interval_ = process.key_frame_interval;
num_temporal_layers_ = process.num_temporal_layers;
@@ -332,49 +401,61 @@
denoising_on_ = process.denoising_on;
SetUpCodecConfig();
// Update the layers and the codec with the initial rates.
- bit_rate_ = target_bit_rate[0];
- frame_rate_ = input_frame_rate[0];
+ bit_rate_ = rate_profile.target_bit_rate[0];
+ frame_rate_ = rate_profile.input_frame_rate[0];
SetLayerRates();
+ // Set the initial target size for key frame.
+ target_size_key_frame_initial_ = 0.5 * kInitialBufferSize *
+ bit_rate_layer_[0];
processor_->SetRates(bit_rate_, frame_rate_);
// Process each frame, up to |num_frames|.
+ int num_frames = rate_profile.num_frames;
int update_index = 0;
- ResetRateControlMetrics(frame_index_rate_update[update_index + 1]);
+ ResetRateControlMetrics(
+ rate_profile.frame_index_rate_update[update_index + 1]);
int frame_number = 0;
+ VideoFrameType frame_type = kDeltaFrame;
while (processor_->ProcessFrame(frame_number) &&
frame_number < num_frames) {
// Get the layer index for the frame |frame_number|.
LayerIndexForFrame(frame_number);
+ frame_type = FrameType(frame_number);
// Counter for whole sequence run.
++frame_number;
// Counters for each rate update.
++num_frames_per_update_[layer_];
++num_frames_total_;
- UpdateRateControlMetrics(frame_number,
- max_encoding_rate_mismatch[update_index]);
+ UpdateRateControlMetrics(frame_number, frame_type);
// If we hit another/next update, verify stats for current state and
// update layers and codec with new rates.
- if (frame_number == frame_index_rate_update[update_index + 1]) {
- VerifyRateControl(update_index,
- max_frame_size_mismatch[update_index],
- max_encoding_rate_mismatch[update_index],
- max_time_hit_target[update_index],
- max_num_dropped_frames[update_index],
- num_spatial_resizes[update_index]);
+ if (frame_number ==
+ rate_profile.frame_index_rate_update[update_index + 1]) {
+ VerifyRateControl(
+ update_index,
+ rc_metrics[update_index].max_key_frame_size_mismatch,
+ rc_metrics[update_index].max_delta_frame_size_mismatch,
+ rc_metrics[update_index].max_encoding_rate_mismatch,
+ rc_metrics[update_index].max_time_hit_target,
+ rc_metrics[update_index].max_num_dropped_frames,
+ rc_metrics[update_index].num_spatial_resizes);
// Update layer rates and the codec with new rates.
++update_index;
- bit_rate_ = target_bit_rate[update_index];
- frame_rate_ = input_frame_rate[update_index];
+ bit_rate_ = rate_profile.target_bit_rate[update_index];
+ frame_rate_ = rate_profile.input_frame_rate[update_index];
SetLayerRates();
- ResetRateControlMetrics(frame_index_rate_update[update_index + 1]);
+ ResetRateControlMetrics(rate_profile.
+ frame_index_rate_update[update_index + 1]);
processor_->SetRates(bit_rate_, frame_rate_);
}
}
- VerifyRateControl(update_index,
- max_frame_size_mismatch[update_index],
- max_encoding_rate_mismatch[update_index],
- max_time_hit_target[update_index],
- max_num_dropped_frames[update_index],
- num_spatial_resizes[update_index]);
+ VerifyRateControl(
+ update_index,
+ rc_metrics[update_index].max_key_frame_size_mismatch,
+ rc_metrics[update_index].max_delta_frame_size_mismatch,
+ rc_metrics[update_index].max_encoding_rate_mismatch,
+ rc_metrics[update_index].max_time_hit_target,
+ rc_metrics[update_index].max_num_dropped_frames,
+ rc_metrics[update_index].num_spatial_resizes);
EXPECT_EQ(num_frames, frame_number);
EXPECT_EQ(num_frames + 1, static_cast<int>(stats_.stats_.size()));
@@ -398,126 +479,134 @@
psnr_result.average, psnr_result.min,
ssim_result.average, ssim_result.min);
stats_.PrintSummary();
- EXPECT_GT(psnr_result.average, minimum_avg_psnr);
- EXPECT_GT(psnr_result.min, minimum_min_psnr);
- EXPECT_GT(ssim_result.average, minimum_avg_ssim);
- EXPECT_GT(ssim_result.min, minimum_min_ssim);
+ EXPECT_GT(psnr_result.average, quality_metrics.minimum_avg_psnr);
+ EXPECT_GT(psnr_result.min, quality_metrics.minimum_min_psnr);
+ EXPECT_GT(ssim_result.average, quality_metrics.minimum_avg_ssim);
+ EXPECT_GT(ssim_result.min, quality_metrics.minimum_min_ssim);
}
};
+void SetRateProfilePars(RateProfile* rate_profile,
+ int update_index,
+ int bit_rate,
+ int frame_rate,
+ int frame_index_rate_update) {
+ rate_profile->target_bit_rate[update_index] = bit_rate;
+ rate_profile->input_frame_rate[update_index] = frame_rate;
+ rate_profile->frame_index_rate_update[update_index] = frame_index_rate_update;
+}
+
+void SetCodecParameters(CodecConfigPars* process_settings,
+ float packet_loss,
+ int key_frame_interval,
+ int num_temporal_layers,
+ bool error_concealment_on,
+ bool denoising_on) {
+ process_settings->packet_loss = packet_loss;
+ process_settings->key_frame_interval = key_frame_interval;
+ process_settings->num_temporal_layers = num_temporal_layers,
+ process_settings->error_concealment_on = error_concealment_on;
+ process_settings->denoising_on = denoising_on;
+}
+
+void SetQualityMetrics(QualityMetrics* quality_metrics,
+ double minimum_avg_psnr,
+ double minimum_min_psnr,
+ double minimum_avg_ssim,
+ double minimum_min_ssim) {
+ quality_metrics->minimum_avg_psnr = minimum_avg_psnr;
+ quality_metrics->minimum_min_psnr = minimum_min_psnr;
+ quality_metrics->minimum_avg_ssim = minimum_avg_ssim;
+ quality_metrics->minimum_min_ssim = minimum_min_ssim;
+}
+
+void SetRateControlMetrics(RateControlMetrics* rc_metrics,
+ int update_index,
+ int max_num_dropped_frames,
+ int max_key_frame_size_mismatch,
+ int max_delta_frame_size_mismatch,
+ int max_encoding_rate_mismatch,
+ int max_time_hit_target,
+ int num_spatial_resizes) {
+ rc_metrics[update_index].max_num_dropped_frames = max_num_dropped_frames;
+ rc_metrics[update_index].max_key_frame_size_mismatch =
+ max_key_frame_size_mismatch;
+ rc_metrics[update_index].max_delta_frame_size_mismatch =
+ max_delta_frame_size_mismatch;
+ rc_metrics[update_index].max_encoding_rate_mismatch =
+ max_encoding_rate_mismatch;
+ rc_metrics[update_index].max_time_hit_target = max_time_hit_target;
+ rc_metrics[update_index].num_spatial_resizes = num_spatial_resizes;
+}
+
// Run with no packet loss and fixed bitrate. Quality should be very high.
// One key frame (first frame only) in sequence. Setting |key_frame_interval|
// to -1 below means no periodic key frames in test.
TEST_F(VideoProcessorIntegrationTest, ProcessZeroPacketLoss) {
// Bitrate and frame rate profile.
- int target_bit_rate[] = {500}; // kbps
- int input_frame_rate[] = {kFrameRate};
- int frame_index_rate_update[] = {0, kNbrFramesShort + 1};
- int num_frames = kNbrFramesShort;
+ RateProfile rate_profile;
+ SetRateProfilePars(&rate_profile, 0, 500, 30, 0);
+ rate_profile.frame_index_rate_update[1] = kNbrFramesShort + 1;
+ rate_profile.num_frames = kNbrFramesShort;
// Codec/network settings.
CodecConfigPars process_settings;
- process_settings.packet_loss = 0.0f;
- process_settings.key_frame_interval = -1;
- process_settings.num_temporal_layers = 1;
- process_settings.error_concealment_on = true;
- process_settings.denoising_on = true;
+ SetCodecParameters(&process_settings, 0.0f, -1, 1, true, true);
// Metrics for expected quality.
- double minimum_avg_psnr = 36;
- double minimum_min_psnr = 32;
- double minimum_avg_ssim = 0.9;
- double minimum_min_ssim = 0.9;
- // Metrics for rate control: rate mismatch metrics are defined as percentages.
- // |max_time_hit_target| is defined as number of frames, after a rate update
- // is made to the encoder, for the encoder to reach within
- // |kPercTargetvsActualMismatch| of new target rate.
- int max_num_dropped_frames[] = {0};
- int max_frame_size_mismatch[] = {20};
- int max_encoding_rate_mismatch[] = {15};
- int max_time_hit_target[] = {15};
- int num_spatial_resizes[] = {0};
- ProcessFramesAndVerify(minimum_avg_psnr, minimum_min_psnr,
- minimum_avg_ssim, minimum_min_ssim,
- target_bit_rate, input_frame_rate,
- frame_index_rate_update, num_frames, process_settings,
- max_frame_size_mismatch, max_encoding_rate_mismatch,
- max_time_hit_target, max_num_dropped_frames,
- num_spatial_resizes);
+ QualityMetrics quality_metrics;
+ SetQualityMetrics(&quality_metrics, 36.0, 34.0, 0.90, 0.90);
+ // Metrics for rate control.
+ RateControlMetrics rc_metrics[1];
+ SetRateControlMetrics(rc_metrics, 0, 0, 40, 20, 10, 15, 0);
+ ProcessFramesAndVerify(quality_metrics,
+ rate_profile,
+ process_settings,
+ rc_metrics);
}
// Run with 5% packet loss and fixed bitrate. Quality should be a bit lower.
// One key frame (first frame only) in sequence.
TEST_F(VideoProcessorIntegrationTest, Process5PercentPacketLoss) {
- // Bitrate and frame rate profile, and codec settings.
- int target_bit_rate[] = {500}; // kbps
- int input_frame_rate[] = {kFrameRate};
- int frame_index_rate_update[] = {0, kNbrFramesShort + 1};
- int num_frames = kNbrFramesShort;
+ // Bitrate and frame rate profile.
+ RateProfile rate_profile;
+ SetRateProfilePars(&rate_profile, 0, 500, 30, 0);
+ rate_profile.frame_index_rate_update[1] = kNbrFramesShort + 1;
+ rate_profile.num_frames = kNbrFramesShort;
// Codec/network settings.
CodecConfigPars process_settings;
- process_settings.packet_loss = 0.05f;
- process_settings.key_frame_interval = -1;
- process_settings.num_temporal_layers = 1;
- process_settings.error_concealment_on = true;
- process_settings.denoising_on = true;
+ SetCodecParameters(&process_settings, 0.05f, -1, 1, true, true);
// Metrics for expected quality.
- double minimum_avg_psnr = 21;
- double minimum_min_psnr = 16;
- double minimum_avg_ssim = 0.6;
- double minimum_min_ssim = 0.4;
- // Metrics for rate control: rate mismatch metrics are defined as percentages.
- // |max_time_hit_target| is defined as number of frames, after a rate update
- // is made to the encoder, for the encoder to reach within
- // |kPercTargetvsActualMismatch| of new target rate.
- int max_num_dropped_frames[] = {0};
- int max_frame_size_mismatch[] = {25};
- int max_encoding_rate_mismatch[] = {15};
- int max_time_hit_target[] = {15};
- int num_spatial_resizes[] = {0};
- ProcessFramesAndVerify(minimum_avg_psnr, minimum_min_psnr,
- minimum_avg_ssim, minimum_min_ssim,
- target_bit_rate, input_frame_rate,
- frame_index_rate_update, num_frames, process_settings,
- max_frame_size_mismatch, max_encoding_rate_mismatch,
- max_time_hit_target, max_num_dropped_frames,
- num_spatial_resizes);
+ QualityMetrics quality_metrics;
+ SetQualityMetrics(&quality_metrics, 21.0, 16.0, 0.60, 0.40);
+ // Metrics for rate control.
+ RateControlMetrics rc_metrics[1];
+ SetRateControlMetrics(rc_metrics, 0, 0, 40, 20, 10, 15, 0);
+ ProcessFramesAndVerify(quality_metrics,
+ rate_profile,
+ process_settings,
+ rc_metrics);
}
// Run with 10% packet loss and fixed bitrate. Quality should be even lower.
// One key frame (first frame only) in sequence.
TEST_F(VideoProcessorIntegrationTest, Process10PercentPacketLoss) {
- // Bitrate and frame rate profile, and codec settings.
- int target_bit_rate[] = {500}; // kbps
- int input_frame_rate[] = {kFrameRate};
- int frame_index_rate_update[] = {0, kNbrFramesShort + 1};
- int num_frames = kNbrFramesShort;
+ // Bitrate and frame rate profile.
+ RateProfile rate_profile;
+ SetRateProfilePars(&rate_profile, 0, 500, 30, 0);
+ rate_profile.frame_index_rate_update[1] = kNbrFramesShort + 1;
+ rate_profile.num_frames = kNbrFramesShort;
// Codec/network settings.
CodecConfigPars process_settings;
- process_settings.packet_loss = 0.1f;
- process_settings.key_frame_interval = -1;
- process_settings.num_temporal_layers = 1;
- process_settings.error_concealment_on = true;
- process_settings.denoising_on = true;
+ SetCodecParameters(&process_settings, 0.1f, -1, 1, true, true);
// Metrics for expected quality.
- double minimum_avg_psnr = 19;
- double minimum_min_psnr = 16;
- double minimum_avg_ssim = 0.5;
- double minimum_min_ssim = 0.35;
- // Metrics for rate control: rate mismatch metrics are defined as percentages.
- // |max_time_hit_target| is defined as number of frames, after a rate update
- // is made to the encoder, for the encoder to reach within
- // |kPercTargetvsActualMismatch| of new target rate.
- int max_num_dropped_frames[] = {0};
- int max_frame_size_mismatch[] = {25};
- int max_encoding_rate_mismatch[] = {15};
- int max_time_hit_target[] = {15};
- int num_spatial_resizes[] = {0};
- ProcessFramesAndVerify(minimum_avg_psnr, minimum_min_psnr,
- minimum_avg_ssim, minimum_min_ssim,
- target_bit_rate, input_frame_rate,
- frame_index_rate_update, num_frames, process_settings,
- max_frame_size_mismatch, max_encoding_rate_mismatch,
- max_time_hit_target, max_num_dropped_frames,
- num_spatial_resizes);
+ QualityMetrics quality_metrics;
+ SetQualityMetrics(&quality_metrics, 19.0, 16.0, 0.50, 0.35);
+ // Metrics for rate control.
+ RateControlMetrics rc_metrics[1];
+ SetRateControlMetrics(rc_metrics, 0, 0, 40, 20, 10, 15, 0);
+ ProcessFramesAndVerify(quality_metrics,
+ rate_profile,
+ process_settings,
+ rc_metrics);
}
// Run with no packet loss, with varying bitrate (3 rate updates):
@@ -525,39 +614,28 @@
// target rate/per-frame bandwidth (for each rate update) is within limits.
// One key frame (first frame only) in sequence.
TEST_F(VideoProcessorIntegrationTest, ProcessNoLossChangeBitRate) {
- // Bitrate and frame rate profile, and codec settings.
- int target_bit_rate[] = {200, 800, 500}; // kbps
- int input_frame_rate[] = {30, 30, 30};
- int frame_index_rate_update[] = {0, 100, 200, kNbrFramesLong + 1};
- int num_frames = kNbrFramesLong;
+ // Bitrate and frame rate profile.
+ RateProfile rate_profile;
+ SetRateProfilePars(&rate_profile, 0, 200, 30, 0);
+ SetRateProfilePars(&rate_profile, 1, 800, 30, 100);
+ SetRateProfilePars(&rate_profile, 2, 500, 30, 200);
+ rate_profile.frame_index_rate_update[3] = kNbrFramesLong + 1;
+ rate_profile.num_frames = kNbrFramesLong;
// Codec/network settings.
CodecConfigPars process_settings;
- process_settings.packet_loss = 0.0f;
- process_settings.key_frame_interval = -1;
- process_settings.num_temporal_layers = 1;
- process_settings.error_concealment_on = true;
- process_settings.denoising_on = true;
+ SetCodecParameters(&process_settings, 0.0f, -1, 1, true, true);
// Metrics for expected quality.
- double minimum_avg_psnr = 34;
- double minimum_min_psnr = 32;
- double minimum_avg_ssim = 0.85;
- double minimum_min_ssim = 0.8;
- // Metrics for rate control: rate mismatch metrics are defined as percentages.
- // |max_time_hit_target| is defined as number of frames, after a rate update
- // is made to the encoder, for the encoder to reach within
- // |kPercTargetvsActualMismatch| of new target rate.
- int max_num_dropped_frames[] = {0, 0, 0};
- int max_frame_size_mismatch[] = {20, 25, 25};
- int max_encoding_rate_mismatch[] = {10, 20, 15};
- int max_time_hit_target[] = {15, 10, 10};
- int num_spatial_resizes[] = {0, 0, 0};
- ProcessFramesAndVerify(minimum_avg_psnr, minimum_min_psnr,
- minimum_avg_ssim, minimum_min_ssim,
- target_bit_rate, input_frame_rate,
- frame_index_rate_update, num_frames, process_settings,
- max_frame_size_mismatch, max_encoding_rate_mismatch,
- max_time_hit_target, max_num_dropped_frames,
- num_spatial_resizes);
+ QualityMetrics quality_metrics;
+ SetQualityMetrics(&quality_metrics, 34.0, 32.0, 0.85, 0.80);
+ // Metrics for rate control.
+ RateControlMetrics rc_metrics[3];
+ SetRateControlMetrics(rc_metrics, 0, 0, 45, 20, 10, 15, 0);
+ SetRateControlMetrics(rc_metrics, 1, 0, 0, 25, 20, 10, 0);
+ SetRateControlMetrics(rc_metrics, 2, 0, 0, 25, 15, 10, 0);
+ ProcessFramesAndVerify(quality_metrics,
+ rate_profile,
+ process_settings,
+ rc_metrics);
}
// Run with no packet loss, with an update (decrease) in frame rate.
@@ -569,41 +647,32 @@
// metrics avergaed over whole sequence run.
TEST_F(VideoProcessorIntegrationTest, ProcessNoLossChangeFrameRateFrameDrop) {
config_.networking_config.packet_loss_probability = 0;
- // Bitrate and frame rate profile, and codec settings.
- int target_bit_rate[] = {80, 80, 80}; // kbps
- int input_frame_rate[] = {30, 15, 10};
- int frame_index_rate_update[] = {0, 100, 200, kNbrFramesLong + 1};
- int num_frames = kNbrFramesLong;
+ // Bitrate and frame rate profile.
+ RateProfile rate_profile;
+ SetRateProfilePars(&rate_profile, 0, 80, 30, 0);
+ SetRateProfilePars(&rate_profile, 1, 80, 15, 100);
+ SetRateProfilePars(&rate_profile, 2, 80, 10, 200);
+ rate_profile.frame_index_rate_update[3] = kNbrFramesLong + 1;
+ rate_profile.num_frames = kNbrFramesLong;
// Codec/network settings.
CodecConfigPars process_settings;
- process_settings.packet_loss = 0.0f;
- process_settings.key_frame_interval = -1;
- process_settings.num_temporal_layers = 1;
- process_settings.error_concealment_on = true;
- process_settings.denoising_on = true;
+ SetCodecParameters(&process_settings, 0.0f, -1, 1, true, true);
// Metrics for expected quality.
- double minimum_avg_psnr = 31;
- double minimum_min_psnr = 24;
- double minimum_avg_ssim = 0.8;
- double minimum_min_ssim = 0.7;
- // Metrics for rate control: rate mismatch metrics are defined as percentages.
- // |max_time_hit_target| is defined as number of frames, after a rate update
- // is made to the encoder, for the encoder to reach within
- // |kPercTargetvsActualMismatch| of new target rate.
- int max_num_dropped_frames[] = {25, 10, 0};
- int max_frame_size_mismatch[] = {60, 25, 20};
- int max_encoding_rate_mismatch[] = {40, 10, 10};
- // At the low per-frame bandwidth for this scene, encoder can't hit target
- // rate before first update.
- int max_time_hit_target[] = {100, 40, 10};
- int num_spatial_resizes[] = {0, 0, 0};
- ProcessFramesAndVerify(minimum_avg_psnr, minimum_min_psnr,
- minimum_avg_ssim, minimum_min_ssim,
- target_bit_rate, input_frame_rate,
- frame_index_rate_update, num_frames, process_settings,
- max_frame_size_mismatch, max_encoding_rate_mismatch,
- max_time_hit_target, max_num_dropped_frames,
- num_spatial_resizes);
+ QualityMetrics quality_metrics;
+ SetQualityMetrics(&quality_metrics, 31.0, 23.0, 0.80, 0.65);
+ quality_metrics.minimum_avg_psnr = 31;
+ quality_metrics.minimum_min_psnr = 23;
+ quality_metrics.minimum_avg_ssim = 0.8;
+ quality_metrics.minimum_min_ssim = 0.65;
+ // Metrics for rate control.
+ RateControlMetrics rc_metrics[3];
+ SetRateControlMetrics(rc_metrics, 0, 40, 20, 75, 15, 60, 0);
+ SetRateControlMetrics(rc_metrics, 1, 10, 0, 25, 10, 35, 0);
+ SetRateControlMetrics(rc_metrics, 2, 0, 0, 20, 10, 10, 0);
+ ProcessFramesAndVerify(quality_metrics,
+ rate_profile,
+ process_settings,
+ rc_metrics);
}
// Run with no packet loss, at low bitrate, then increase rate somewhat.
@@ -615,41 +684,31 @@
// is a memory leak with resizing and error concealment.
TEST_F(VideoProcessorIntegrationTest, ProcessNoLossSpatialResizeFrameDrop) {
config_.networking_config.packet_loss_probability = 0;
- // Bitrate and frame rate profile, and codec settings.
- int target_bit_rate[] = {80, 200, 200}; // kbps
- int input_frame_rate[] = {30, 30, 30};
- int frame_index_rate_update[] = {0, 120, 240, kNbrFramesLong + 1};
- int num_frames = kNbrFramesLong;
+ // Bitrate and frame rate profile.
+ RateProfile rate_profile;
+ SetRateProfilePars(&rate_profile, 0, 80, 30, 0);
+ SetRateProfilePars(&rate_profile, 1, 200, 30, 120);
+ SetRateProfilePars(&rate_profile, 2, 200, 30, 240);
+ rate_profile.frame_index_rate_update[3] = kNbrFramesLong + 1;
+ rate_profile.num_frames = kNbrFramesLong;
// Codec/network settings.
CodecConfigPars process_settings;
- process_settings.packet_loss = 0.0f;
- process_settings.key_frame_interval = 120;
- process_settings.num_temporal_layers = 1;
- process_settings.error_concealment_on = false;
- process_settings.denoising_on = true;
+ SetCodecParameters(&process_settings, 0.0f, 120, 1, true, true);
// Metrics for expected quality.: lower quality on average from up-sampling
// the down-sampled portion of the run, in case resizer is on.
- double minimum_avg_psnr = 29;
- double minimum_min_psnr = 20;
- double minimum_avg_ssim = 0.75;
- double minimum_min_ssim = 0.6;
- // Metrics for rate control: rate mismatch metrics are defined as percentages.
- // |max_time_hit_target| is defined as number of frames, after a rate update
- // is made to the encoder, for the encoder to reach within
- // |kPercTargetvsActualMismatch| of new target rate.
- int max_num_dropped_frames[] = {25, 15, 0};
- int max_frame_size_mismatch[] = {60, 30, 30};
- int max_encoding_rate_mismatch[] = {30, 20, 15};
- // At this low rate for this scene, can't hit target rate before first update.
- int max_time_hit_target[] = {120, 15, 25};
- int num_spatial_resizes[] = {0, 1, 1};
- ProcessFramesAndVerify(minimum_avg_psnr, minimum_min_psnr,
- minimum_avg_ssim, minimum_min_ssim,
- target_bit_rate, input_frame_rate,
- frame_index_rate_update, num_frames, process_settings,
- max_frame_size_mismatch, max_encoding_rate_mismatch,
- max_time_hit_target, max_num_dropped_frames,
- num_spatial_resizes);
+ QualityMetrics quality_metrics;
+ SetQualityMetrics(&quality_metrics, 29.0, 20.0, 0.75, 0.60);
+ // Metrics for rate control.
+ RateControlMetrics rc_metrics[3];
+ SetRateControlMetrics(rc_metrics, 0, 45, 20, 75, 20, 70, 0);
+ SetRateControlMetrics(rc_metrics, 1, 20, 35, 30, 20, 15, 1);
+ // TODO(marpan): Lower this mismatch value for key frame when we upgrade to
+ // new libvpx: currently there is bug in the QP selection.
+ SetRateControlMetrics(rc_metrics, 2, 0, 110, 30, 15, 25, 1);
+ ProcessFramesAndVerify(quality_metrics,
+ rate_profile,
+ process_settings,
+ rc_metrics);
}
// Run with no packet loss, with 3 temporal layers, with a rate update in the
@@ -659,38 +718,25 @@
// One key frame (first frame only) in sequence, so no spatial resizing.
TEST_F(VideoProcessorIntegrationTest, ProcessNoLossTemporalLayers) {
config_.networking_config.packet_loss_probability = 0;
- // Bitrate and frame rate profile, and codec settings.
- int target_bit_rate[] = {200, 400}; // kbps
- int input_frame_rate[] = {30, 30};
- int frame_index_rate_update[] = {0, 150, kNbrFramesLong + 1};
- int num_frames = kNbrFramesLong;
+ // Bitrate and frame rate profile.
+ RateProfile rate_profile;
+ SetRateProfilePars(&rate_profile, 0, 200, 30, 0);
+ SetRateProfilePars(&rate_profile, 1, 400, 30, 150);
+ rate_profile.frame_index_rate_update[2] = kNbrFramesLong + 1;
+ rate_profile.num_frames = kNbrFramesLong;
// Codec/network settings.
CodecConfigPars process_settings;
- process_settings.packet_loss = 0.0f;
- process_settings.key_frame_interval = -1;
- process_settings.num_temporal_layers = 3;
- process_settings.error_concealment_on = true;
- process_settings.denoising_on = false;
+ SetCodecParameters(&process_settings, 0.0f, -1, 3, true, false);
// Metrics for expected quality.
- double minimum_avg_psnr = 33;
- double minimum_min_psnr = 30;
- double minimum_avg_ssim = 0.85;
- double minimum_min_ssim = 0.80;
- // Metrics for rate control: rate mismatch metrics are defined as percentages.
- // |max_time_hit_target| is defined as number of frames, after a rate update
- // is made to the encoder, for the encoder to reach within
- // |kPercTargetvsActualMismatch| of new target rate.
- int max_num_dropped_frames[] = {0, 0};
- int max_frame_size_mismatch[] = {30, 30};
- int max_encoding_rate_mismatch[] = {10, 12};
- int max_time_hit_target[] = {15, 15};
- int num_spatial_resizes[] = {0, 0};
- ProcessFramesAndVerify(minimum_avg_psnr, minimum_min_psnr,
- minimum_avg_ssim, minimum_min_ssim,
- target_bit_rate, input_frame_rate,
- frame_index_rate_update, num_frames, process_settings,
- max_frame_size_mismatch, max_encoding_rate_mismatch,
- max_time_hit_target, max_num_dropped_frames,
- num_spatial_resizes);
+ QualityMetrics quality_metrics;
+ SetQualityMetrics(&quality_metrics, 32.5, 30.0, 0.85, 0.80);
+ // Metrics for rate control.
+ RateControlMetrics rc_metrics[2];
+ SetRateControlMetrics(rc_metrics, 0, 0, 20, 30, 10, 10, 0);
+ SetRateControlMetrics(rc_metrics, 1, 0, 0, 30, 15, 10, 1);
+ ProcessFramesAndVerify(quality_metrics,
+ rate_profile,
+ process_settings,
+ rc_metrics);
}
} // namespace webrtc