Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(211)

Side by Side Diff: modules/video_coding/codecs/test/videoprocessor_integrationtest.cc

Issue 3009423002: VideoProcessorIntegrationTest: Group member variables into two structs containing target/actual rate (Closed)
Patch Set: rebase Created 3 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « modules/video_coding/codecs/test/videoprocessor_integrationtest.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "modules/video_coding/codecs/test/videoprocessor_integrationtest.h" 11 #include "modules/video_coding/codecs/test/videoprocessor_integrationtest.h"
12 12
13 #include <algorithm>
13 #include <utility> 14 #include <utility>
14 15
15 #if defined(WEBRTC_ANDROID) 16 #if defined(WEBRTC_ANDROID)
16 #include "modules/video_coding/codecs/test/android_test_initializer.h" 17 #include "modules/video_coding/codecs/test/android_test_initializer.h"
17 #include "sdk/android/src/jni/androidmediadecoder_jni.h" 18 #include "sdk/android/src/jni/androidmediadecoder_jni.h"
18 #include "sdk/android/src/jni/androidmediaencoder_jni.h" 19 #include "sdk/android/src/jni/androidmediaencoder_jni.h"
19 #elif defined(WEBRTC_IOS) 20 #elif defined(WEBRTC_IOS)
20 #include "modules/video_coding/codecs/test/objc_codec_h264_test.h" 21 #include "modules/video_coding/codecs/test/objc_codec_h264_test.h"
21 #endif 22 #endif
22 23
(...skipping 11 matching lines...) Expand all
34 #include "system_wrappers/include/sleep.h" 35 #include "system_wrappers/include/sleep.h"
35 #include "test/testsupport/fileutils.h" 36 #include "test/testsupport/fileutils.h"
36 #include "test/testsupport/metrics/video_metrics.h" 37 #include "test/testsupport/metrics/video_metrics.h"
37 #include "test/video_codec_settings.h" 38 #include "test/video_codec_settings.h"
38 39
39 namespace webrtc { 40 namespace webrtc {
40 namespace test { 41 namespace test {
41 42
42 namespace { 43 namespace {
43 44
44 const int kPercTargetvsActualMismatch = 20; 45 const int kMaxBitrateMismatchPercent = 20;
45 const int kBaseKeyFrameInterval = 3000; 46 const int kBaseKeyFrameInterval = 3000;
46 47
47 // Parameters from VP8 wrapper, which control target size of key frames. 48 // Parameters from VP8 wrapper, which control target size of key frames.
48 const float kInitialBufferSize = 0.5f; 49 const float kInitialBufferSize = 0.5f;
49 const float kOptimalBufferSize = 0.6f; 50 const float kOptimalBufferSize = 0.6f;
50 const float kScaleKeyFrameSize = 0.5f; 51 const float kScaleKeyFrameSize = 0.5f;
51 52
52 void VerifyQuality(const QualityMetricsResult& psnr_result, 53 void VerifyQuality(const QualityMetricsResult& psnr_result,
53 const QualityMetricsResult& ssim_result, 54 const QualityMetricsResult& ssim_result,
54 const QualityThresholds& quality_thresholds) { 55 const QualityThresholds& quality_thresholds) {
55 EXPECT_GT(psnr_result.average, quality_thresholds.min_avg_psnr); 56 EXPECT_GT(psnr_result.average, quality_thresholds.min_avg_psnr);
56 EXPECT_GT(psnr_result.min, quality_thresholds.min_min_psnr); 57 EXPECT_GT(psnr_result.min, quality_thresholds.min_min_psnr);
57 EXPECT_GT(ssim_result.average, quality_thresholds.min_avg_ssim); 58 EXPECT_GT(ssim_result.average, quality_thresholds.min_avg_ssim);
58 EXPECT_GT(ssim_result.min, quality_thresholds.min_min_ssim); 59 EXPECT_GT(ssim_result.min, quality_thresholds.min_min_ssim);
59 } 60 }
60 61
62 void PrintQualityMetrics(const QualityMetricsResult& psnr_result,
63 const QualityMetricsResult& ssim_result) {
64 printf("PSNR avg: %f, min: %f\n", psnr_result.average, psnr_result.min);
65 printf("SSIM avg: %f, min: %f\n", ssim_result.average, ssim_result.min);
66 printf("\n");
67 }
68
61 int NumberOfTemporalLayers(const VideoCodec& codec_settings) { 69 int NumberOfTemporalLayers(const VideoCodec& codec_settings) {
62 if (codec_settings.codecType == kVideoCodecVP8) { 70 if (codec_settings.codecType == kVideoCodecVP8) {
63 return codec_settings.VP8().numberOfTemporalLayers; 71 return codec_settings.VP8().numberOfTemporalLayers;
64 } else if (codec_settings.codecType == kVideoCodecVP9) { 72 } else if (codec_settings.codecType == kVideoCodecVP9) {
65 return codec_settings.VP9().numberOfTemporalLayers; 73 return codec_settings.VP9().numberOfTemporalLayers;
66 } else { 74 } else {
67 return 1; 75 return 1;
68 } 76 }
69 } 77 }
70 78
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 int framerate_fps, 141 int framerate_fps,
134 int frame_index_rate_update) { 142 int frame_index_rate_update) {
135 rate_profile->target_bit_rate[rate_update_index] = bitrate_kbps; 143 rate_profile->target_bit_rate[rate_update_index] = bitrate_kbps;
136 rate_profile->input_frame_rate[rate_update_index] = framerate_fps; 144 rate_profile->input_frame_rate[rate_update_index] = framerate_fps;
137 rate_profile->frame_index_rate_update[rate_update_index] = 145 rate_profile->frame_index_rate_update[rate_update_index] =
138 frame_index_rate_update; 146 frame_index_rate_update;
139 } 147 }
140 148
141 void VideoProcessorIntegrationTest::AddRateControlThresholds( 149 void VideoProcessorIntegrationTest::AddRateControlThresholds(
142 int max_num_dropped_frames, 150 int max_num_dropped_frames,
143 int max_key_frame_size_mismatch, 151 int max_key_framesize_mismatch_percent,
144 int max_delta_frame_size_mismatch, 152 int max_delta_framesize_mismatch_percent,
145 int max_encoding_rate_mismatch, 153 int max_bitrate_mismatch_percent,
146 int max_time_hit_target, 154 int max_num_frames_to_hit_target,
147 int num_spatial_resizes, 155 int num_spatial_resizes,
148 int num_key_frames, 156 int num_key_frames,
149 std::vector<RateControlThresholds>* rc_thresholds) { 157 std::vector<RateControlThresholds>* rc_thresholds) {
150 RTC_DCHECK(rc_thresholds); 158 RTC_DCHECK(rc_thresholds);
151 159
152 rc_thresholds->emplace_back(); 160 rc_thresholds->emplace_back();
153 RateControlThresholds* rc_threshold = &rc_thresholds->back(); 161 RateControlThresholds* rc_threshold = &rc_thresholds->back();
154 rc_threshold->max_num_dropped_frames = max_num_dropped_frames; 162 rc_threshold->max_num_dropped_frames = max_num_dropped_frames;
155 rc_threshold->max_key_frame_size_mismatch = max_key_frame_size_mismatch; 163 rc_threshold->max_key_framesize_mismatch_percent =
156 rc_threshold->max_delta_frame_size_mismatch = max_delta_frame_size_mismatch; 164 max_key_framesize_mismatch_percent;
157 rc_threshold->max_encoding_rate_mismatch = max_encoding_rate_mismatch; 165 rc_threshold->max_delta_framesize_mismatch_percent =
158 rc_threshold->max_time_hit_target = max_time_hit_target; 166 max_delta_framesize_mismatch_percent;
167 rc_threshold->max_bitrate_mismatch_percent = max_bitrate_mismatch_percent;
168 rc_threshold->max_num_frames_to_hit_target = max_num_frames_to_hit_target;
159 rc_threshold->num_spatial_resizes = num_spatial_resizes; 169 rc_threshold->num_spatial_resizes = num_spatial_resizes;
160 rc_threshold->num_key_frames = num_key_frames; 170 rc_threshold->num_key_frames = num_key_frames;
161 } 171 }
162 172
163 // Processes all frames in the clip and verifies the result. 173 // Processes all frames in the clip and verifies the result.
164 void VideoProcessorIntegrationTest::ProcessFramesAndMaybeVerify( 174 void VideoProcessorIntegrationTest::ProcessFramesAndMaybeVerify(
165 const RateProfile& rate_profile, 175 const RateProfile& rate_profile,
166 const std::vector<RateControlThresholds>* rc_thresholds, 176 const std::vector<RateControlThresholds>* rc_thresholds,
167 const QualityThresholds* quality_thresholds, 177 const QualityThresholds* quality_thresholds,
168 const VisualizationParams* visualization_params) { 178 const VisualizationParams* visualization_params) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 } 221 }
212 222
213 // Give the VideoProcessor pipeline some time to process the last frame, 223 // Give the VideoProcessor pipeline some time to process the last frame,
214 // and then release the codecs. 224 // and then release the codecs.
215 if (config_.hw_encoder || config_.hw_decoder) { 225 if (config_.hw_encoder || config_.hw_decoder) {
216 SleepMs(1 * rtc::kNumMillisecsPerSec); 226 SleepMs(1 * rtc::kNumMillisecsPerSec);
217 } 227 }
218 ReleaseAndCloseObjects(&task_queue); 228 ReleaseAndCloseObjects(&task_queue);
219 229
220 // Calculate and print rate control statistics. 230 // Calculate and print rate control statistics.
231 std::vector<int> num_dropped_frames;
232 std::vector<int> num_spatial_resizes;
233 sync_event.Reset();
234 task_queue.PostTask(
235 [this, &num_dropped_frames, &num_spatial_resizes, &sync_event]() {
236 num_dropped_frames = processor_->NumberDroppedFramesPerRateUpdate();
237 num_spatial_resizes = processor_->NumberSpatialResizesPerRateUpdate();
238 sync_event.Set();
239 });
240 sync_event.Wait(rtc::Event::kForever);
241
221 rate_update_index = 0; 242 rate_update_index = 0;
222 frame_number = 0; 243 frame_number = 0;
223 ResetRateControlMetrics(rate_update_index, rate_profile); 244 ResetRateControlMetrics(rate_update_index, rate_profile);
224 std::vector<int> num_dropped_frames;
225 std::vector<int> num_resize_actions;
226 sync_event.Reset();
227 task_queue.PostTask(
228 [this, &num_dropped_frames, &num_resize_actions, &sync_event]() {
229 num_dropped_frames = processor_->NumberDroppedFramesPerRateUpdate();
230 num_resize_actions = processor_->NumberSpatialResizesPerRateUpdate();
231 sync_event.Set();
232 });
233 sync_event.Wait(rtc::Event::kForever);
234 while (frame_number < num_frames) { 245 while (frame_number < num_frames) {
235 UpdateRateControlMetrics(frame_number); 246 UpdateRateControlMetrics(frame_number);
236 247
237 ++frame_number; 248 ++frame_number;
238 249
239 if (frame_number == 250 if (frame_number ==
240 rate_profile.frame_index_rate_update[rate_update_index + 1]) { 251 rate_profile.frame_index_rate_update[rate_update_index + 1]) {
241 PrintAndMaybeVerifyRateControlMetrics(rate_update_index, rc_thresholds, 252 PrintRateControlMetrics(rate_update_index, num_dropped_frames,
242 num_dropped_frames, 253 num_spatial_resizes);
243 num_resize_actions); 254 VerifyRateControlMetrics(rate_update_index, rc_thresholds,
255 num_dropped_frames, num_spatial_resizes);
244 ++rate_update_index; 256 ++rate_update_index;
245 ResetRateControlMetrics(rate_update_index, rate_profile); 257 ResetRateControlMetrics(rate_update_index, rate_profile);
246 } 258 }
247 } 259 }
248 PrintAndMaybeVerifyRateControlMetrics(rate_update_index, rc_thresholds, 260
249 num_dropped_frames, num_resize_actions); 261 PrintRateControlMetrics(rate_update_index, num_dropped_frames,
262 num_spatial_resizes);
263 VerifyRateControlMetrics(rate_update_index, rc_thresholds, num_dropped_frames,
264 num_spatial_resizes);
250 265
251 // Calculate and print other statistics. 266 // Calculate and print other statistics.
252 EXPECT_EQ(num_frames, static_cast<int>(stats_.size())); 267 EXPECT_EQ(num_frames, static_cast<int>(stats_.size()));
253 stats_.PrintSummary(); 268 stats_.PrintSummary();
254 269
255 // Calculate and print image quality statistics. 270 // Calculate and print image quality statistics.
256 // TODO(marpan): Should compute these quality metrics per SetRates update. 271 // TODO(marpan): Should compute these quality metrics per SetRates update.
257 QualityMetricsResult psnr_result, ssim_result; 272 QualityMetricsResult psnr_result, ssim_result;
258 EXPECT_EQ(0, I420MetricsFromFiles(config_.input_filename.c_str(), 273 EXPECT_EQ(0, I420MetricsFromFiles(config_.input_filename.c_str(),
259 config_.output_filename.c_str(), 274 config_.output_filename.c_str(),
260 config_.codec_settings.width, 275 config_.codec_settings.width,
261 config_.codec_settings.height, &psnr_result, 276 config_.codec_settings.height, &psnr_result,
262 &ssim_result)); 277 &ssim_result));
263 if (quality_thresholds) { 278 if (quality_thresholds) {
264 VerifyQuality(psnr_result, ssim_result, *quality_thresholds); 279 VerifyQuality(psnr_result, ssim_result, *quality_thresholds);
265 } 280 }
266 printf("PSNR avg: %f, min: %f\nSSIM avg: %f, min: %f\n", psnr_result.average, 281 PrintQualityMetrics(psnr_result, ssim_result);
267 psnr_result.min, ssim_result.average, ssim_result.min);
268 printf("\n");
269 282
270 // Remove analysis file. 283 // Remove analysis file.
271 if (remove(config_.output_filename.c_str()) < 0) { 284 if (remove(config_.output_filename.c_str()) < 0) {
272 fprintf(stderr, "Failed to remove temporary file!\n"); 285 fprintf(stderr, "Failed to remove temporary file!\n");
273 } 286 }
274 } 287 }
275 288
276 void VideoProcessorIntegrationTest::CreateEncoderAndDecoder() { 289 void VideoProcessorIntegrationTest::CreateEncoderAndDecoder() {
277 std::unique_ptr<cricket::WebRtcVideoEncoderFactory> encoder_factory; 290 std::unique_ptr<cricket::WebRtcVideoEncoderFactory> encoder_factory;
278 if (config_.hw_encoder) { 291 if (config_.hw_encoder) {
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 if (decoded_frame_writer_) { 444 if (decoded_frame_writer_) {
432 decoded_frame_writer_->Close(); 445 decoded_frame_writer_->Close();
433 } 446 }
434 } 447 }
435 448
436 // For every encoded frame, update the rate control metrics. 449 // For every encoded frame, update the rate control metrics.
437 void VideoProcessorIntegrationTest::UpdateRateControlMetrics(int frame_number) { 450 void VideoProcessorIntegrationTest::UpdateRateControlMetrics(int frame_number) {
438 RTC_CHECK_GE(frame_number, 0); 451 RTC_CHECK_GE(frame_number, 0);
439 452
440 const int tl_idx = TemporalLayerIndexForFrame(frame_number); 453 const int tl_idx = TemporalLayerIndexForFrame(frame_number);
441 ++num_frames_per_update_[tl_idx]; 454 ++actual_.num_frames_layer[tl_idx];
442 ++num_frames_total_; 455 ++actual_.num_frames;
443 456
444 const FrameStatistic* frame_stat = stats_.GetFrame(frame_number); 457 const FrameStatistic* frame_stat = stats_.GetFrame(frame_number);
445 FrameType frame_type = frame_stat->frame_type; 458 FrameType frame_type = frame_stat->frame_type;
446 float encoded_size_kbits = 459 float framesize_kbits = frame_stat->encoded_frame_size_bytes * 8.0f / 1000.0f;
447 frame_stat->encoded_frame_size_bytes * 8.0f / 1000.0f;
448 460
449 // Update layer data. 461 // Update rate mismatch relative to per-frame bandwidth.
450 // Update rate mismatch relative to per-frame bandwidth for delta frames.
451 if (frame_type == kVideoFrameDelta) { 462 if (frame_type == kVideoFrameDelta) {
452 // TODO(marpan): Should we count dropped (zero size) frames in mismatch? 463 // TODO(marpan): Should we count dropped (zero size) frames in mismatch?
453 sum_frame_size_mismatch_[tl_idx] += 464 actual_.sum_delta_framesize_mismatch_layer[tl_idx] +=
454 fabs(encoded_size_kbits - per_frame_bandwidth_[tl_idx]) / 465 fabs(framesize_kbits - target_.framesize_kbits_layer[tl_idx]) /
455 per_frame_bandwidth_[tl_idx]; 466 target_.framesize_kbits_layer[tl_idx];
456 } else { 467 } else {
457 float target_size = (frame_number == 0) ? target_size_key_frame_initial_ 468 float key_framesize_kbits = (frame_number == 0)
458 : target_size_key_frame_; 469 ? target_.key_framesize_kbits_initial
459 sum_key_frame_size_mismatch_ += 470 : target_.key_framesize_kbits;
460 fabs(encoded_size_kbits - target_size) / target_size; 471 actual_.sum_key_framesize_mismatch +=
461 num_key_frames_ += 1; 472 fabs(framesize_kbits - key_framesize_kbits) / key_framesize_kbits;
473 ++actual_.num_key_frames;
462 } 474 }
463 sum_encoded_frame_size_[tl_idx] += encoded_size_kbits; 475 actual_.sum_framesize_kbits += framesize_kbits;
464 // Encoding bit rate per temporal layer: from the start of the update/run 476 actual_.sum_framesize_kbits_layer[tl_idx] += framesize_kbits;
465 // to the current frame. 477
466 encoding_bitrate_[tl_idx] = sum_encoded_frame_size_[tl_idx] * 478 // Encoded bitrate: from the start of the update/run to current frame.
467 framerate_layer_[tl_idx] / 479 actual_.kbps = actual_.sum_framesize_kbits * target_.fps / actual_.num_frames;
468 num_frames_per_update_[tl_idx]; 480 actual_.kbps_layer[tl_idx] = actual_.sum_framesize_kbits_layer[tl_idx] *
469 // Total encoding rate: from the start of the update/run to current frame. 481 target_.fps_layer[tl_idx] /
470 sum_encoded_frame_size_total_ += encoded_size_kbits; 482 actual_.num_frames_layer[tl_idx];
471 encoding_bitrate_total_ = 483
472 sum_encoded_frame_size_total_ * framerate_ / num_frames_total_; 484 // Number of frames to hit target bitrate.
473 perc_encoding_rate_mismatch_ = 485 if (actual_.BitrateMismatchPercent(target_.kbps) <
474 100 * fabs(encoding_bitrate_total_ - bitrate_kbps_) / bitrate_kbps_; 486 kMaxBitrateMismatchPercent) {
475 if (perc_encoding_rate_mismatch_ < kPercTargetvsActualMismatch && 487 actual_.num_frames_to_hit_target =
476 !encoding_rate_within_target_) { 488 std::min(actual_.num_frames, actual_.num_frames_to_hit_target);
477 num_frames_to_hit_target_ = num_frames_total_;
478 encoding_rate_within_target_ = true;
479 } 489 }
480 } 490 }
481 491
482 // Verify expected behavior of rate control and print out data. 492 // Verify expected behavior of rate control.
483 void VideoProcessorIntegrationTest::PrintAndMaybeVerifyRateControlMetrics( 493 void VideoProcessorIntegrationTest::VerifyRateControlMetrics(
484 int rate_update_index, 494 int rate_update_index,
485 const std::vector<RateControlThresholds>* rc_thresholds, 495 const std::vector<RateControlThresholds>* rc_thresholds,
486 const std::vector<int>& num_dropped_frames, 496 const std::vector<int>& num_dropped_frames,
487 const std::vector<int>& num_resize_actions) { 497 const std::vector<int>& num_spatial_resizes) const {
488 printf( 498 if (!rc_thresholds)
489 "Rate update #%d:\n" 499 return;
490 " Target bitrate : %d\n"
491 " Encoded bitrate : %f\n"
492 " Frame rate : %d\n",
493 rate_update_index, bitrate_kbps_, encoding_bitrate_total_, framerate_);
494 printf(
495 " # processed frames : %d\n"
496 " # frames to convergence: %d\n"
497 " # dropped frames : %d\n"
498 " # spatial resizes : %d\n",
499 num_frames_total_, num_frames_to_hit_target_,
500 num_dropped_frames[rate_update_index],
501 num_resize_actions[rate_update_index]);
502 500
503 const RateControlThresholds* rc_threshold = nullptr; 501 const RateControlThresholds& rc_threshold =
504 if (rc_thresholds) { 502 (*rc_thresholds)[rate_update_index];
505 rc_threshold = &(*rc_thresholds)[rate_update_index];
506 503
507 EXPECT_LE(perc_encoding_rate_mismatch_, 504 EXPECT_LE(num_dropped_frames[rate_update_index],
508 rc_threshold->max_encoding_rate_mismatch); 505 rc_threshold.max_num_dropped_frames);
509 } 506 EXPECT_EQ(rc_threshold.num_spatial_resizes,
510 if (num_key_frames_ > 0) { 507 num_spatial_resizes[rate_update_index]);
511 int perc_key_frame_size_mismatch = 508
512 100 * sum_key_frame_size_mismatch_ / num_key_frames_; 509 EXPECT_LE(actual_.num_frames_to_hit_target,
513 printf( 510 rc_threshold.max_num_frames_to_hit_target);
514 " # key frames : %d\n" 511 EXPECT_EQ(rc_threshold.num_key_frames, actual_.num_key_frames);
515 " Key frame rate mismatch: %d\n", 512 EXPECT_LE(actual_.KeyFrameSizeMismatchPercent(),
516 num_key_frames_, perc_key_frame_size_mismatch); 513 rc_threshold.max_key_framesize_mismatch_percent);
517 if (rc_threshold) { 514 EXPECT_LE(actual_.BitrateMismatchPercent(target_.kbps),
518 EXPECT_LE(perc_key_frame_size_mismatch, 515 rc_threshold.max_bitrate_mismatch_percent);
519 rc_threshold->max_key_frame_size_mismatch);
520 }
521 }
522 516
523 const int num_temporal_layers = 517 const int num_temporal_layers =
524 NumberOfTemporalLayers(config_.codec_settings); 518 NumberOfTemporalLayers(config_.codec_settings);
525 for (int i = 0; i < num_temporal_layers; i++) { 519 for (int i = 0; i < num_temporal_layers; ++i) {
526 int perc_frame_size_mismatch = 520 EXPECT_LE(actual_.DeltaFrameSizeMismatchPercent(i),
527 100 * sum_frame_size_mismatch_[i] / num_frames_per_update_[i]; 521 rc_threshold.max_delta_framesize_mismatch_percent);
528 int perc_encoding_rate_mismatch = 522 EXPECT_LE(actual_.BitrateMismatchPercent(i, target_.kbps_layer[i]),
529 100 * fabs(encoding_bitrate_[i] - bitrate_layer_[i]) / 523 rc_threshold.max_bitrate_mismatch_percent);
530 bitrate_layer_[i]; 524 }
531 printf( 525 }
532 " Temporal layer #%d:\n" 526
533 " Target layer bitrate : %f\n" 527 void VideoProcessorIntegrationTest::PrintRateControlMetrics(
534 " Layer frame rate : %f\n" 528 int rate_update_index,
535 " Layer per frame bandwidth : %f\n" 529 const std::vector<int>& num_dropped_frames,
536 " Layer encoding bitrate : %f\n" 530 const std::vector<int>& num_spatial_resizes) const {
537 " Layer percent frame size mismatch : %d\n" 531 printf("Rate update #%d:\n", rate_update_index);
538 " Layer percent encoding rate mismatch: %d\n" 532 printf(" Target bitrate : %d\n", target_.kbps);
539 " # frames processed per layer : %d\n", 533 printf(" Encoded bitrate : %f\n", actual_.kbps);
540 i, bitrate_layer_[i], framerate_layer_[i], per_frame_bandwidth_[i], 534 printf(" Frame rate : %d\n", target_.fps);
541 encoding_bitrate_[i], perc_frame_size_mismatch, 535 printf(" # processed frames : %d\n", actual_.num_frames);
542 perc_encoding_rate_mismatch, num_frames_per_update_[i]); 536 printf(" # frames to convergence: %d\n", actual_.num_frames_to_hit_target);
543 if (rc_threshold) { 537 printf(" # dropped frames : %d\n",
544 EXPECT_LE(perc_frame_size_mismatch, 538 num_dropped_frames[rate_update_index]);
545 rc_threshold->max_delta_frame_size_mismatch); 539 printf(" # spatial resizes : %d\n",
546 EXPECT_LE(perc_encoding_rate_mismatch, 540 num_spatial_resizes[rate_update_index]);
547 rc_threshold->max_encoding_rate_mismatch); 541 printf(" # key frames : %d\n", actual_.num_key_frames);
548 } 542 printf(" Key frame rate mismatch: %d\n",
543 actual_.KeyFrameSizeMismatchPercent());
544
545 const int num_temporal_layers =
546 NumberOfTemporalLayers(config_.codec_settings);
547 for (int i = 0; i < num_temporal_layers; ++i) {
548 printf(" Temporal layer #%d:\n", i);
549 printf(" Layer target bitrate : %f\n", target_.kbps_layer[i]);
550 printf(" Layer frame rate : %f\n", target_.fps_layer[i]);
551 printf(" Layer per frame bandwidth : %f\n",
552 target_.framesize_kbits_layer[i]);
553 printf(" Layer encoded bitrate : %f\n", actual_.kbps_layer[i]);
554 printf(" Layer frame size %% mismatch : %d\n",
555 actual_.DeltaFrameSizeMismatchPercent(i));
556 printf(" Layer bitrate %% mismatch : %d\n",
557 actual_.BitrateMismatchPercent(i, target_.kbps_layer[i]));
558 printf(" # processed frames per layer: %d\n", actual_.num_frames_layer[i]);
549 } 559 }
550 printf("\n"); 560 printf("\n");
551
552 if (rc_threshold) {
553 EXPECT_LE(num_frames_to_hit_target_, rc_threshold->max_time_hit_target);
554 EXPECT_LE(num_dropped_frames[rate_update_index],
555 rc_threshold->max_num_dropped_frames);
556 EXPECT_EQ(rc_threshold->num_spatial_resizes,
557 num_resize_actions[rate_update_index]);
558 EXPECT_EQ(rc_threshold->num_key_frames, num_key_frames_);
559 }
560 } 561 }
561 562
562 // Temporal layer index corresponding to frame number, for up to 3 layers. 563 // Temporal layer index corresponding to frame number, for up to 3 layers.
563 int VideoProcessorIntegrationTest::TemporalLayerIndexForFrame( 564 int VideoProcessorIntegrationTest::TemporalLayerIndexForFrame(
564 int frame_number) const { 565 int frame_number) const {
565 const int num_temporal_layers =
566 NumberOfTemporalLayers(config_.codec_settings);
567 int tl_idx = -1; 566 int tl_idx = -1;
568 switch (num_temporal_layers) { 567 switch (NumberOfTemporalLayers(config_.codec_settings)) {
569 case 1: 568 case 1:
570 tl_idx = 0; 569 tl_idx = 0;
571 break; 570 break;
572 case 2: 571 case 2:
573 // temporal layer 0: 0 2 4 ... 572 // temporal layer 0: 0 2 4 ...
574 // temporal layer 1: 1 3 573 // temporal layer 1: 1 3
575 tl_idx = (frame_number % 2 == 0) ? 0 : 1; 574 tl_idx = (frame_number % 2 == 0) ? 0 : 1;
576 break; 575 break;
577 case 3: 576 case 3:
578 // temporal layer 0: 0 4 8 ... 577 // temporal layer 0: 0 4 8 ...
(...skipping 12 matching lines...) Expand all
591 break; 590 break;
592 } 591 }
593 return tl_idx; 592 return tl_idx;
594 } 593 }
595 594
596 // Reset quantities before each encoder rate update. 595 // Reset quantities before each encoder rate update.
597 void VideoProcessorIntegrationTest::ResetRateControlMetrics( 596 void VideoProcessorIntegrationTest::ResetRateControlMetrics(
598 int rate_update_index, 597 int rate_update_index,
599 const RateProfile& rate_profile) { 598 const RateProfile& rate_profile) {
600 // Set new rates. 599 // Set new rates.
601 bitrate_kbps_ = rate_profile.target_bit_rate[rate_update_index]; 600 target_.kbps = rate_profile.target_bit_rate[rate_update_index];
602 framerate_ = rate_profile.input_frame_rate[rate_update_index]; 601 target_.fps = rate_profile.input_frame_rate[rate_update_index];
603 const int num_temporal_layers = 602 SetRatesPerTemporalLayer();
604 NumberOfTemporalLayers(config_.codec_settings); 603
605 RTC_DCHECK_LE(num_temporal_layers, kMaxNumTemporalLayers); 604 // Set key frame target sizes.
606 for (int i = 0; i < num_temporal_layers; i++) {
607 float bit_rate_ratio = kVp8LayerRateAlloction[num_temporal_layers - 1][i];
608 if (i > 0) {
609 float bit_rate_delta_ratio =
610 kVp8LayerRateAlloction[num_temporal_layers - 1][i] -
611 kVp8LayerRateAlloction[num_temporal_layers - 1][i - 1];
612 bitrate_layer_[i] = bitrate_kbps_ * bit_rate_delta_ratio;
613 } else {
614 bitrate_layer_[i] = bitrate_kbps_ * bit_rate_ratio;
615 }
616 framerate_layer_[i] =
617 framerate_ / static_cast<float>(1 << (num_temporal_layers - 1));
618 }
619 if (num_temporal_layers == 3) {
620 framerate_layer_[2] = framerate_ / 2.0f;
621 }
622 if (rate_update_index == 0) { 605 if (rate_update_index == 0) {
623 target_size_key_frame_initial_ = 606 target_.key_framesize_kbits_initial =
624 0.5 * kInitialBufferSize * bitrate_layer_[0]; 607 0.5 * kInitialBufferSize * target_.kbps_layer[0];
625 } 608 }
626 609
627 // Reset rate control metrics.
628 for (int i = 0; i < num_temporal_layers; i++) {
629 num_frames_per_update_[i] = 0;
630 sum_frame_size_mismatch_[i] = 0.0f;
631 sum_encoded_frame_size_[i] = 0.0f;
632 encoding_bitrate_[i] = 0.0f;
633 // Update layer per-frame-bandwidth.
634 per_frame_bandwidth_[i] = static_cast<float>(bitrate_layer_[i]) /
635 static_cast<float>(framerate_layer_[i]);
636 }
637 // Set maximum size of key frames, following setting in the VP8 wrapper. 610 // Set maximum size of key frames, following setting in the VP8 wrapper.
638 float max_key_size = kScaleKeyFrameSize * kOptimalBufferSize * framerate_; 611 float max_key_size = kScaleKeyFrameSize * kOptimalBufferSize * target_.fps;
639 // We don't know exact target size of the key frames (except for first one), 612 // We don't know exact target size of the key frames (except for first one),
640 // but the minimum in libvpx is ~|3 * per_frame_bandwidth| and maximum is 613 // but the minimum in libvpx is ~|3 * per_frame_bandwidth| and maximum is
641 // set by |max_key_size_ * per_frame_bandwidth|. Take middle point/average 614 // set by |max_key_size_ * per_frame_bandwidth|. Take middle point/average
642 // as reference for mismatch. Note key frames always correspond to base 615 // as reference for mismatch. Note key frames always correspond to base
643 // layer frame in this test. 616 // layer frame in this test.
644 target_size_key_frame_ = 0.5 * (3 + max_key_size) * per_frame_bandwidth_[0]; 617 target_.key_framesize_kbits =
645 num_frames_total_ = 0; 618 0.5 * (3 + max_key_size) * target_.framesize_kbits_layer[0];
646 sum_encoded_frame_size_total_ = 0.0f; 619
647 encoding_bitrate_total_ = 0.0f; 620 // Reset rate control metrics.
648 perc_encoding_rate_mismatch_ = 0.0f; 621 actual_ = TestResults();
649 num_frames_to_hit_target_ = 622 actual_.num_frames_to_hit_target = // Set to max number of frames.
650 rate_profile.frame_index_rate_update[rate_update_index + 1]; 623 rate_profile.frame_index_rate_update[rate_update_index + 1];
651 encoding_rate_within_target_ = false; 624 }
652 sum_key_frame_size_mismatch_ = 0.0; 625
653 num_key_frames_ = 0; 626 void VideoProcessorIntegrationTest::SetRatesPerTemporalLayer() {
627 const int num_temporal_layers =
628 NumberOfTemporalLayers(config_.codec_settings);
629 RTC_DCHECK_LE(num_temporal_layers, kMaxNumTemporalLayers);
630
631 for (int i = 0; i < num_temporal_layers; ++i) {
632 float bitrate_ratio;
633 if (i > 0) {
634 bitrate_ratio = kVp8LayerRateAlloction[num_temporal_layers - 1][i] -
635 kVp8LayerRateAlloction[num_temporal_layers - 1][i - 1];
636 } else {
637 bitrate_ratio = kVp8LayerRateAlloction[num_temporal_layers - 1][i];
638 }
639 target_.kbps_layer[i] = target_.kbps * bitrate_ratio;
640 target_.fps_layer[i] =
641 target_.fps / static_cast<float>(1 << (num_temporal_layers - 1));
642 }
643 if (num_temporal_layers == 3) {
644 target_.fps_layer[2] = target_.fps / 2.0f;
645 }
646
647 // Update layer per-frame-bandwidth.
648 for (int i = 0; i < num_temporal_layers; ++i) {
649 target_.framesize_kbits_layer[i] =
650 target_.kbps_layer[i] / target_.fps_layer[i];
651 }
654 } 652 }
655 653
656 } // namespace test 654 } // namespace test
657 } // namespace webrtc 655 } // namespace webrtc
OLDNEW
« no previous file with comments | « modules/video_coding/codecs/test/videoprocessor_integrationtest.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698