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

Side by Side Diff: webrtc/modules/video_coding/codecs/test/videoprocessor_integrationtest.h

Issue 2997283002: VideoProcessorIntegrationTest: make it runnable on a task queue. (Closed)
Patch Set: Created 3 years, 4 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
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 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 #ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_INTEGRATIONTEST_H _ 11 #ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_INTEGRATIONTEST_H _
12 #define WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_INTEGRATIONTEST_H _ 12 #define WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_INTEGRATIONTEST_H _
13 13
14 #include <math.h> 14 #include <math.h>
15 15
16 #include <limits> 16 #include <limits>
17 #include <memory> 17 #include <memory>
18 #include <string> 18 #include <string>
19 #include <utility> 19 #include <utility>
20 #include <vector>
20 21
21 #if defined(WEBRTC_ANDROID) 22 #if defined(WEBRTC_ANDROID)
22 #include "webrtc/modules/video_coding/codecs/test/android_test_initializer.h" 23 #include "webrtc/modules/video_coding/codecs/test/android_test_initializer.h"
23 #include "webrtc/sdk/android/src/jni/androidmediadecoder_jni.h" 24 #include "webrtc/sdk/android/src/jni/androidmediadecoder_jni.h"
24 #include "webrtc/sdk/android/src/jni/androidmediaencoder_jni.h" 25 #include "webrtc/sdk/android/src/jni/androidmediaencoder_jni.h"
25 #elif defined(WEBRTC_IOS) 26 #elif defined(WEBRTC_IOS)
26 #include "webrtc/modules/video_coding/codecs/test/objc_codec_h264_test.h" 27 #include "webrtc/modules/video_coding/codecs/test/objc_codec_h264_test.h"
27 #endif 28 #endif
28 29
29 #include "webrtc/media/engine/internaldecoderfactory.h" 30 #include "webrtc/media/engine/internaldecoderfactory.h"
30 #include "webrtc/media/engine/internalencoderfactory.h" 31 #include "webrtc/media/engine/internalencoderfactory.h"
31 #include "webrtc/media/engine/webrtcvideodecoderfactory.h" 32 #include "webrtc/media/engine/webrtcvideodecoderfactory.h"
32 #include "webrtc/media/engine/webrtcvideoencoderfactory.h" 33 #include "webrtc/media/engine/webrtcvideoencoderfactory.h"
33 #include "webrtc/modules/video_coding/codecs/test/packet_manipulator.h" 34 #include "webrtc/modules/video_coding/codecs/test/packet_manipulator.h"
34 #include "webrtc/modules/video_coding/codecs/test/videoprocessor.h" 35 #include "webrtc/modules/video_coding/codecs/test/videoprocessor.h"
35 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h" 36 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h"
36 #include "webrtc/modules/video_coding/include/video_codec_interface.h" 37 #include "webrtc/modules/video_coding/include/video_codec_interface.h"
37 #include "webrtc/modules/video_coding/include/video_coding.h" 38 #include "webrtc/modules/video_coding/include/video_coding.h"
38 #include "webrtc/modules/video_coding/utility/ivf_file_writer.h" 39 #include "webrtc/modules/video_coding/utility/ivf_file_writer.h"
39 #include "webrtc/rtc_base/checks.h" 40 #include "webrtc/rtc_base/checks.h"
41 #include "webrtc/rtc_base/event.h"
40 #include "webrtc/rtc_base/file.h" 42 #include "webrtc/rtc_base/file.h"
41 #include "webrtc/rtc_base/logging.h" 43 #include "webrtc/rtc_base/logging.h"
42 #include "webrtc/rtc_base/ptr_util.h" 44 #include "webrtc/rtc_base/ptr_util.h"
45 #include "webrtc/system_wrappers/include/sleep.h"
43 #include "webrtc/test/gtest.h" 46 #include "webrtc/test/gtest.h"
44 #include "webrtc/test/testsupport/fileutils.h" 47 #include "webrtc/test/testsupport/fileutils.h"
45 #include "webrtc/test/testsupport/frame_reader.h" 48 #include "webrtc/test/testsupport/frame_reader.h"
46 #include "webrtc/test/testsupport/frame_writer.h" 49 #include "webrtc/test/testsupport/frame_writer.h"
47 #include "webrtc/test/testsupport/metrics/video_metrics.h" 50 #include "webrtc/test/testsupport/metrics/video_metrics.h"
48 #include "webrtc/test/testsupport/packet_reader.h" 51 #include "webrtc/test/testsupport/packet_reader.h"
49 #include "webrtc/test/video_codec_settings.h" 52 #include "webrtc/test/video_codec_settings.h"
50 #include "webrtc/typedefs.h" 53 #include "webrtc/typedefs.h"
51 54
52 namespace webrtc { 55 namespace webrtc {
53 namespace test { 56 namespace test {
54 57
55 const int kMaxNumRateUpdates = 3; 58 const int kMaxNumRateUpdates = 3;
56 const int kMaxNumTemporalLayers = 3; 59 const int kMaxNumTemporalLayers = 3;
57 60
58 const int kPercTargetvsActualMismatch = 20; 61 const int kPercTargetvsActualMismatch = 20;
59 const int kBaseKeyFrameInterval = 3000; 62 const int kBaseKeyFrameInterval = 3000;
60 63
61 // Parameters from VP8 wrapper, which control target size of key frames. 64 // Parameters from VP8 wrapper, which control target size of key frames.
62 const float kInitialBufferSize = 0.5f; 65 const float kInitialBufferSize = 0.5f;
63 const float kOptimalBufferSize = 0.6f; 66 const float kOptimalBufferSize = 0.6f;
64 const float kScaleKeyFrameSize = 0.5f; 67 const float kScaleKeyFrameSize = 0.5f;
65 68
66 // Thresholds for the quality metrics. Defaults are maximally minimal. 69 // Thresholds for the quality metrics. Defaults are maximally minimal.
67 struct QualityThresholds { 70 struct QualityThresholds {
68 QualityThresholds() {}
69 QualityThresholds(double min_avg_psnr, 71 QualityThresholds(double min_avg_psnr,
70 double min_min_psnr, 72 double min_min_psnr,
71 double min_avg_ssim, 73 double min_avg_ssim,
72 double min_min_ssim) 74 double min_min_ssim)
73 : min_avg_psnr(min_avg_psnr), 75 : min_avg_psnr(min_avg_psnr),
74 min_min_psnr(min_min_psnr), 76 min_min_psnr(min_min_psnr),
75 min_avg_ssim(min_avg_ssim), 77 min_avg_ssim(min_avg_ssim),
76 min_min_ssim(min_min_ssim) {} 78 min_min_ssim(min_min_ssim) {}
77 double min_avg_psnr = std::numeric_limits<double>::min(); 79 double min_avg_psnr;
78 double min_min_psnr = std::numeric_limits<double>::min(); 80 double min_min_psnr;
79 double min_avg_ssim = 0.0; 81 double min_avg_ssim;
80 double min_min_ssim = 0.0; 82 double min_min_ssim;
81 }; 83 };
82 84
83 // The sequence of bit rate and frame rate changes for the encoder, the frame 85 // The sequence of bit rate and frame rate changes for the encoder, the frame
84 // number where the changes are made, and the total number of frames for the 86 // number where the changes are made, and the total number of frames for the
85 // test. 87 // test.
86 struct RateProfile { 88 struct RateProfile {
87 int target_bit_rate[kMaxNumRateUpdates]; 89 int target_bit_rate[kMaxNumRateUpdates];
88 int input_frame_rate[kMaxNumRateUpdates]; 90 int input_frame_rate[kMaxNumRateUpdates];
89 int frame_index_rate_update[kMaxNumRateUpdates + 1]; 91 int frame_index_rate_update[kMaxNumRateUpdates + 1];
90 int num_frames; 92 int num_frames;
91 }; 93 };
92 94
93 // Thresholds for the rate control metrics. The rate mismatch thresholds are 95 // Thresholds for the rate control metrics. The rate mismatch thresholds are
94 // defined as percentages. |max_time_hit_target| is defined as number of frames, 96 // defined as percentages. |max_time_hit_target| is defined as number of frames,
95 // after a rate update is made to the encoder, for the encoder to reach within 97 // after a rate update is made to the encoder, for the encoder to reach within
96 // |kPercTargetvsActualMismatch| of new target rate. The thresholds are defined 98 // |kPercTargetvsActualMismatch| of new target rate. The thresholds are defined
97 // for each rate update sequence. 99 // for each rate update sequence.
98 struct RateControlThresholds { 100 struct RateControlThresholds {
99 int max_num_dropped_frames; 101 int max_num_dropped_frames;
100 int max_key_frame_size_mismatch; 102 int max_key_frame_size_mismatch;
101 int max_delta_frame_size_mismatch; 103 int max_delta_frame_size_mismatch;
102 int max_encoding_rate_mismatch; 104 int max_encoding_rate_mismatch;
103 int max_time_hit_target; 105 int max_time_hit_target;
104 int num_spatial_resizes; // Set to -1 to disable check. 106 int num_spatial_resizes;
105 int num_key_frames; // Set to -1 to disable check. 107 int num_key_frames;
106 }; 108 };
107 109
108 // Should video files be saved persistently to disk for post-run visualization? 110 // Should video files be saved persistently to disk for post-run visualization?
109 struct VisualizationParams { 111 struct VisualizationParams {
110 bool save_encoded_ivf; 112 bool save_encoded_ivf;
111 bool save_decoded_y4m; 113 bool save_decoded_y4m;
112 }; 114 };
113 115
114 // Integration test for video processor. Encodes+decodes a clip and 116 // Integration test for video processor. Encodes+decodes a clip and
115 // writes it to the output directory. After completion, quality metrics 117 // writes it to the output directory. After completion, quality metrics
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 177
176 EXPECT_TRUE(encoder_) << "Encoder not successfully created."; 178 EXPECT_TRUE(encoder_) << "Encoder not successfully created.";
177 EXPECT_TRUE(decoder_) << "Decoder not successfully created."; 179 EXPECT_TRUE(decoder_) << "Decoder not successfully created.";
178 } 180 }
179 181
180 void DestroyEncoderAndDecoder() { 182 void DestroyEncoderAndDecoder() {
181 encoder_factory_->DestroyVideoEncoder(encoder_); 183 encoder_factory_->DestroyVideoEncoder(encoder_);
182 decoder_factory_->DestroyVideoDecoder(decoder_); 184 decoder_factory_->DestroyVideoDecoder(decoder_);
183 } 185 }
184 186
185 void SetUpObjects(const VisualizationParams* visualization_params, 187 void SetUpAndInitObjects(rtc::TaskQueue* task_queue,
186 const int initial_bitrate_kbps, 188 const int initial_bitrate_kbps,
187 const int initial_framerate_fps) { 189 const int initial_framerate_fps,
190 const VisualizationParams* visualization_params) {
188 CreateEncoderAndDecoder(); 191 CreateEncoderAndDecoder();
189 192
190 // Create file objects for quality analysis. 193 // Create file objects for quality analysis.
191 analysis_frame_reader_.reset(new YuvFrameReaderImpl( 194 analysis_frame_reader_.reset(new YuvFrameReaderImpl(
192 config_.input_filename, config_.codec_settings.width, 195 config_.input_filename, config_.codec_settings.width,
193 config_.codec_settings.height)); 196 config_.codec_settings.height));
194 analysis_frame_writer_.reset(new YuvFrameWriterImpl( 197 analysis_frame_writer_.reset(new YuvFrameWriterImpl(
195 config_.output_filename, config_.codec_settings.width, 198 config_.output_filename, config_.codec_settings.width,
196 config_.codec_settings.height)); 199 config_.codec_settings.height));
197 EXPECT_TRUE(analysis_frame_reader_->Init()); 200 EXPECT_TRUE(analysis_frame_reader_->Init());
(...skipping 19 matching lines...) Expand all
217 if (visualization_params->save_decoded_y4m) { 220 if (visualization_params->save_decoded_y4m) {
218 decoded_frame_writer_.reset(new Y4mFrameWriterImpl( 221 decoded_frame_writer_.reset(new Y4mFrameWriterImpl(
219 output_filename_base + ".y4m", config_.codec_settings.width, 222 output_filename_base + ".y4m", config_.codec_settings.width,
220 config_.codec_settings.height, initial_framerate_fps)); 223 config_.codec_settings.height, initial_framerate_fps));
221 EXPECT_TRUE(decoded_frame_writer_->Init()); 224 EXPECT_TRUE(decoded_frame_writer_->Init());
222 } 225 }
223 } 226 }
224 227
225 packet_manipulator_.reset(new PacketManipulatorImpl( 228 packet_manipulator_.reset(new PacketManipulatorImpl(
226 &packet_reader_, config_.networking_config, config_.verbose)); 229 &packet_reader_, config_.networking_config, config_.verbose));
227 processor_ = rtc::MakeUnique<VideoProcessor>( 230
228 encoder_, decoder_, analysis_frame_reader_.get(), 231 config_.codec_settings.startBitrate = initial_bitrate_kbps;
229 analysis_frame_writer_.get(), packet_manipulator_.get(), config_, 232
230 &stats_, encoded_frame_writer_.get(), decoded_frame_writer_.get()); 233 rtc::Event sync_event(false, false);
231 processor_->Init(); 234 task_queue->PostTask([this, &sync_event]() {
235 processor_ = rtc::MakeUnique<VideoProcessor>(
236 encoder_, decoder_, analysis_frame_reader_.get(),
237 analysis_frame_writer_.get(), packet_manipulator_.get(), config_,
238 &stats_, encoded_frame_writer_.get(), decoded_frame_writer_.get());
239 processor_->Init();
240 sync_event.Set();
241 });
242 sync_event.Wait(rtc::Event::kForever);
243 }
244
245 void ReleaseAndCloseObjects(rtc::TaskQueue* task_queue) {
246 rtc::Event sync_event(false, false);
247 task_queue->PostTask([this, &sync_event]() {
248 processor_->Release();
249 sync_event.Set();
250 });
251 sync_event.Wait(rtc::Event::kForever);
252
253 // The VideoProcessor must be ::Release()'d before we destroy the codecs.
254 DestroyEncoderAndDecoder();
255
256 // Close the analysis files before we use them for SSIM/PSNR calculations.
257 analysis_frame_reader_->Close();
258 analysis_frame_writer_->Close();
259
260 // Close visualization files.
261 if (encoded_frame_writer_) {
262 EXPECT_TRUE(encoded_frame_writer_->Close());
263 }
264 if (decoded_frame_writer_) {
265 decoded_frame_writer_->Close();
266 }
232 } 267 }
233 268
234 // Reset quantities after each encoder update, update the target per-frame 269 // Reset quantities after each encoder update, update the target per-frame
235 // bandwidth. 270 // bandwidth.
236 void ResetRateControlMetrics(int num_frames_to_hit_target) { 271 void ResetRateControlMetrics(int num_frames_to_hit_target) {
237 const int num_temporal_layers = 272 const int num_temporal_layers =
238 NumberOfTemporalLayers(config_.codec_settings); 273 NumberOfTemporalLayers(config_.codec_settings);
239 for (int i = 0; i < num_temporal_layers; i++) { 274 for (int i = 0; i < num_temporal_layers; i++) {
240 num_frames_per_update_[i] = 0; 275 num_frames_per_update_[i] = 0;
241 sum_frame_size_mismatch_[i] = 0.0f; 276 sum_frame_size_mismatch_[i] = 0.0f;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 perc_encoding_rate_mismatch_ = 335 perc_encoding_rate_mismatch_ =
301 100 * fabs(encoding_bitrate_total_ - bitrate_kbps_) / bitrate_kbps_; 336 100 * fabs(encoding_bitrate_total_ - bitrate_kbps_) / bitrate_kbps_;
302 if (perc_encoding_rate_mismatch_ < kPercTargetvsActualMismatch && 337 if (perc_encoding_rate_mismatch_ < kPercTargetvsActualMismatch &&
303 !encoding_rate_within_target_) { 338 !encoding_rate_within_target_) {
304 num_frames_to_hit_target_ = num_frames_total_; 339 num_frames_to_hit_target_ = num_frames_total_;
305 encoding_rate_within_target_ = true; 340 encoding_rate_within_target_ = true;
306 } 341 }
307 } 342 }
308 343
309 // Verify expected behavior of rate control and print out data. 344 // Verify expected behavior of rate control and print out data.
310 void VerifyRateControlMetrics(int rate_update_index, 345 void PrintAndMaybeVerifyRateControlMetrics(
311 const RateControlThresholds& rc_expected) { 346 int rate_update_index,
312 int num_dropped_frames = processor_->NumberDroppedFrames(); 347 const std::vector<RateControlThresholds>* rc_thresholds,
313 int num_resize_actions = processor_->NumberSpatialResizes(); 348 const std::vector<int>& num_dropped_frames,
349 const std::vector<int>& num_resize_actions) {
350 const RateControlThresholds* rc_threshold = nullptr;
351 if (rc_thresholds) {
352 rc_threshold = &(*rc_thresholds)[rate_update_index];
353
354 EXPECT_LE(perc_encoding_rate_mismatch_,
355 rc_threshold->max_encoding_rate_mismatch);
356 }
357
314 printf( 358 printf(
315 "Rate update #%d:\n" 359 "Rate update #%d:\n"
316 " Target bitrate : %d\n" 360 " Target bitrate : %d\n"
317 " Encoded bitrate : %f\n" 361 " Encoded bitrate : %f\n"
318 " Frame rate : %d\n", 362 " Frame rate : %d\n",
319 rate_update_index, bitrate_kbps_, encoding_bitrate_total_, framerate_); 363 rate_update_index, bitrate_kbps_, encoding_bitrate_total_, framerate_);
320 printf( 364 printf(
321 " # processed frames : %d\n" 365 " # processed frames : %d\n"
322 " # frames to convergence: %d\n" 366 " # frames to convergence: %d\n"
323 " # dropped frames : %d\n" 367 " # dropped frames : %d\n"
324 " # spatial resizes : %d\n", 368 " # spatial resizes : %d\n",
325 num_frames_total_, num_frames_to_hit_target_, num_dropped_frames, 369 num_frames_total_, num_frames_to_hit_target_,
326 num_resize_actions); 370 num_dropped_frames[rate_update_index],
371 num_resize_actions[rate_update_index]);
327 372
328 EXPECT_LE(perc_encoding_rate_mismatch_,
329 rc_expected.max_encoding_rate_mismatch);
330 if (num_key_frames_ > 0) { 373 if (num_key_frames_ > 0) {
331 int perc_key_frame_size_mismatch = 374 int perc_key_frame_size_mismatch =
332 100 * sum_key_frame_size_mismatch_ / num_key_frames_; 375 100 * sum_key_frame_size_mismatch_ / num_key_frames_;
333 printf( 376 printf(
334 " # key frames : %d\n" 377 " # key frames : %d\n"
335 " Key frame rate mismatch: %d\n", 378 " Key frame rate mismatch: %d\n",
336 num_key_frames_, perc_key_frame_size_mismatch); 379 num_key_frames_, perc_key_frame_size_mismatch);
337 EXPECT_LE(perc_key_frame_size_mismatch, 380 if (rc_threshold) {
338 rc_expected.max_key_frame_size_mismatch); 381 EXPECT_LE(perc_key_frame_size_mismatch,
382 rc_threshold->max_key_frame_size_mismatch);
383 }
339 } 384 }
340 385
341 const int num_temporal_layers = 386 const int num_temporal_layers =
342 NumberOfTemporalLayers(config_.codec_settings); 387 NumberOfTemporalLayers(config_.codec_settings);
343 for (int i = 0; i < num_temporal_layers; i++) { 388 for (int i = 0; i < num_temporal_layers; i++) {
344 int perc_frame_size_mismatch = 389 int perc_frame_size_mismatch =
345 100 * sum_frame_size_mismatch_[i] / num_frames_per_update_[i]; 390 100 * sum_frame_size_mismatch_[i] / num_frames_per_update_[i];
346 int perc_encoding_rate_mismatch = 391 int perc_encoding_rate_mismatch =
347 100 * fabs(encoding_bitrate_[i] - bitrate_layer_[i]) / 392 100 * fabs(encoding_bitrate_[i] - bitrate_layer_[i]) /
348 bitrate_layer_[i]; 393 bitrate_layer_[i];
349 printf( 394 printf(
350 " Temporal layer #%d:\n" 395 " Temporal layer #%d:\n"
351 " Target layer bitrate : %f\n" 396 " Target layer bitrate : %f\n"
352 " Layer frame rate : %f\n" 397 " Layer frame rate : %f\n"
353 " Layer per frame bandwidth : %f\n" 398 " Layer per frame bandwidth : %f\n"
354 " Layer encoding bitrate : %f\n" 399 " Layer encoding bitrate : %f\n"
355 " Layer percent frame size mismatch : %d\n" 400 " Layer percent frame size mismatch : %d\n"
356 " Layer percent encoding rate mismatch: %d\n" 401 " Layer percent encoding rate mismatch: %d\n"
357 " # frames processed per layer : %d\n", 402 " # frames processed per layer : %d\n",
358 i, bitrate_layer_[i], framerate_layer_[i], per_frame_bandwidth_[i], 403 i, bitrate_layer_[i], framerate_layer_[i], per_frame_bandwidth_[i],
359 encoding_bitrate_[i], perc_frame_size_mismatch, 404 encoding_bitrate_[i], perc_frame_size_mismatch,
360 perc_encoding_rate_mismatch, num_frames_per_update_[i]); 405 perc_encoding_rate_mismatch, num_frames_per_update_[i]);
361 EXPECT_LE(perc_frame_size_mismatch, 406 if (rc_threshold) {
362 rc_expected.max_delta_frame_size_mismatch); 407 EXPECT_LE(perc_frame_size_mismatch,
363 EXPECT_LE(perc_encoding_rate_mismatch, 408 rc_threshold->max_delta_frame_size_mismatch);
364 rc_expected.max_encoding_rate_mismatch); 409 EXPECT_LE(perc_encoding_rate_mismatch,
410 rc_threshold->max_encoding_rate_mismatch);
411 }
365 } 412 }
366 printf("\n"); 413 printf("\n");
367 414
368 EXPECT_LE(num_frames_to_hit_target_, rc_expected.max_time_hit_target); 415 if (rc_threshold) {
369 EXPECT_LE(num_dropped_frames, rc_expected.max_num_dropped_frames); 416 EXPECT_LE(num_frames_to_hit_target_, rc_threshold->max_time_hit_target);
370 if (rc_expected.num_spatial_resizes >= 0) { 417 EXPECT_LE(num_dropped_frames[rate_update_index],
371 EXPECT_EQ(rc_expected.num_spatial_resizes, num_resize_actions); 418 rc_threshold->max_num_dropped_frames);
372 } 419 EXPECT_EQ(rc_threshold->num_spatial_resizes,
373 if (rc_expected.num_key_frames >= 0) { 420 num_resize_actions[rate_update_index]);
374 EXPECT_EQ(rc_expected.num_key_frames, num_key_frames_); 421 EXPECT_EQ(rc_threshold->num_key_frames, num_key_frames_);
375 } 422 }
376 } 423 }
377 424
378 static void VerifyQuality(const QualityMetricsResult& psnr_result, 425 static void VerifyQuality(const QualityMetricsResult& psnr_result,
379 const QualityMetricsResult& ssim_result, 426 const QualityMetricsResult& ssim_result,
380 const QualityThresholds& quality_thresholds) { 427 const QualityThresholds& quality_thresholds) {
381 EXPECT_GT(psnr_result.average, quality_thresholds.min_avg_psnr); 428 EXPECT_GT(psnr_result.average, quality_thresholds.min_avg_psnr);
382 EXPECT_GT(psnr_result.min, quality_thresholds.min_min_psnr); 429 EXPECT_GT(psnr_result.min, quality_thresholds.min_min_psnr);
383 EXPECT_GT(ssim_result.average, quality_thresholds.min_avg_ssim); 430 EXPECT_GT(ssim_result.average, quality_thresholds.min_avg_ssim);
384 EXPECT_GT(ssim_result.min, quality_thresholds.min_min_ssim); 431 EXPECT_GT(ssim_result.min, quality_thresholds.min_min_ssim);
385 } 432 }
386 433
387 void VerifyQpParser(int frame_number) {
388 if (!config_.hw_codec &&
389 (config_.codec_settings.codecType == kVideoCodecVP8 ||
390 config_.codec_settings.codecType == kVideoCodecVP9)) {
391 EXPECT_EQ(processor_->GetQpFromEncoder(frame_number),
392 processor_->GetQpFromBitstream(frame_number));
393 }
394 }
395
396 static int NumberOfTemporalLayers(const VideoCodec& codec_settings) { 434 static int NumberOfTemporalLayers(const VideoCodec& codec_settings) {
397 if (codec_settings.codecType == kVideoCodecVP8) { 435 if (codec_settings.codecType == kVideoCodecVP8) {
398 return codec_settings.VP8().numberOfTemporalLayers; 436 return codec_settings.VP8().numberOfTemporalLayers;
399 } else if (codec_settings.codecType == kVideoCodecVP9) { 437 } else if (codec_settings.codecType == kVideoCodecVP9) {
400 return codec_settings.VP9().numberOfTemporalLayers; 438 return codec_settings.VP9().numberOfTemporalLayers;
401 } else { 439 } else {
402 return 1; 440 return 1;
403 } 441 }
404 } 442 }
405 443
(...skipping 23 matching lines...) Expand all
429 tl_idx = 2; 467 tl_idx = 2;
430 } 468 }
431 break; 469 break;
432 default: 470 default:
433 RTC_NOTREACHED(); 471 RTC_NOTREACHED();
434 break; 472 break;
435 } 473 }
436 return tl_idx; 474 return tl_idx;
437 } 475 }
438 476
439 // Set the bit rate and frame rate per temporal layer, for up to 3 layers. 477 void UpdateRates(int rate_update_index, const RateProfile& rate_profile) {
440 void SetTemporalLayerRates() { 478 bitrate_kbps_ = rate_profile.target_bit_rate[rate_update_index];
479 framerate_ = rate_profile.input_frame_rate[rate_update_index];
480
441 const int num_temporal_layers = 481 const int num_temporal_layers =
442 NumberOfTemporalLayers(config_.codec_settings); 482 NumberOfTemporalLayers(config_.codec_settings);
443 RTC_DCHECK_LE(num_temporal_layers, kMaxNumTemporalLayers); 483 RTC_DCHECK_LE(num_temporal_layers, kMaxNumTemporalLayers);
444 for (int i = 0; i < num_temporal_layers; i++) { 484 for (int i = 0; i < num_temporal_layers; i++) {
445 float bit_rate_ratio = kVp8LayerRateAlloction[num_temporal_layers - 1][i]; 485 float bit_rate_ratio = kVp8LayerRateAlloction[num_temporal_layers - 1][i];
446 if (i > 0) { 486 if (i > 0) {
447 float bit_rate_delta_ratio = 487 float bit_rate_delta_ratio =
448 kVp8LayerRateAlloction[num_temporal_layers - 1][i] - 488 kVp8LayerRateAlloction[num_temporal_layers - 1][i] -
449 kVp8LayerRateAlloction[num_temporal_layers - 1][i - 1]; 489 kVp8LayerRateAlloction[num_temporal_layers - 1][i - 1];
450 bitrate_layer_[i] = bitrate_kbps_ * bit_rate_delta_ratio; 490 bitrate_layer_[i] = bitrate_kbps_ * bit_rate_delta_ratio;
451 } else { 491 } else {
452 bitrate_layer_[i] = bitrate_kbps_ * bit_rate_ratio; 492 bitrate_layer_[i] = bitrate_kbps_ * bit_rate_ratio;
453 } 493 }
454 framerate_layer_[i] = 494 framerate_layer_[i] =
455 framerate_ / static_cast<float>(1 << (num_temporal_layers - 1)); 495 framerate_ / static_cast<float>(1 << (num_temporal_layers - 1));
456 } 496 }
457 if (num_temporal_layers == 3) { 497 if (num_temporal_layers == 3) {
458 framerate_layer_[2] = framerate_ / 2.0f; 498 framerate_layer_[2] = framerate_ / 2.0f;
459 } 499 }
460 } 500 }
461 501
462 // Processes all frames in the clip and verifies the result. 502 // Processes all frames in the clip and verifies the result.
463 // TODO(brandtr): Change the second last argument to be a 503 void ProcessFramesAndMaybeVerify(
464 // const std::vector<RateControlThresholds>&, so we can ensure that the user 504 const RateProfile& rate_profile,
465 // does not expect us to do mid-clip rate updates when we are not able to, 505 const std::vector<RateControlThresholds>* rc_thresholds,
466 // e.g., when we are operating in batch mode. 506 const QualityThresholds* quality_thresholds,
467 void ProcessFramesAndVerify(const QualityThresholds& quality_thresholds, 507 const VisualizationParams* visualization_params) {
468 const RateProfile& rate_profile, 508 // The Android HW codec needs to be run on a task queue, so we simply always
469 RateControlThresholds* rc_thresholds, 509 // run the test on a task queue.
470 const VisualizationParams* visualization_params) { 510 rtc::TaskQueue task_queue("VidProc TQ");
471 config_.codec_settings.startBitrate = rate_profile.target_bit_rate[0]; 511 rtc::Event sync_event(false, false);
472 SetUpObjects(visualization_params, rate_profile.target_bit_rate[0], 512
473 rate_profile.input_frame_rate[0]); 513 SetUpAndInitObjects(&task_queue, rate_profile.target_bit_rate[0],
514 rate_profile.input_frame_rate[0], visualization_params);
474 515
475 // Set initial rates. 516 // Set initial rates.
476 bitrate_kbps_ = rate_profile.target_bit_rate[0]; 517 int rate_update_index = 0;
477 framerate_ = rate_profile.input_frame_rate[0]; 518 task_queue.PostTask([this, &rate_profile, rate_update_index] {
478 SetTemporalLayerRates(); 519 processor_->SetRates(rate_profile.target_bit_rate[rate_update_index],
479 // Set the initial target size for key frame. 520 rate_profile.input_frame_rate[rate_update_index]);
521 });
522
523 // Process all frames.
524 int frame_number = 0;
525 const int num_frames = rate_profile.num_frames;
526 RTC_DCHECK_GE(num_frames, 1);
527 while (frame_number < num_frames) {
528 // In order to not overwhelm the OpenMAX buffers in the Android
529 // MediaCodec API, we roughly pace the frames here. The downside
530 // of this is that the encode run will be done in real-time.
531 // TODO(brandtr): Investigate if this is needed on iOS.
532 if (config_.hw_codec) {
533 SleepMs(rtc::kNumMillisecsPerSec /
534 rate_profile.input_frame_rate[rate_update_index]);
535 }
536
537 task_queue.PostTask(
538 [this, frame_number] { processor_->ProcessFrame(frame_number); });
539 ++frame_number;
540
541 if (frame_number ==
542 rate_profile.frame_index_rate_update[rate_update_index + 1]) {
543 ++rate_update_index;
544
545 task_queue.PostTask([this, &rate_profile, rate_update_index] {
546 processor_->SetRates(
547 rate_profile.target_bit_rate[rate_update_index],
548 rate_profile.input_frame_rate[rate_update_index]);
549 });
550 }
551 }
552
553 // TODO(brandtr): Verify the assumption that HW codecs never
554 // drop frames internally.
555 if (config_.hw_codec) {
556 // Ensure that all the frames have been encoded and decoded.
557 int last_decoded_frame_num = -1;
558 int wait_count = 0;
559 while (last_decoded_frame_num != (num_frames - 1) && wait_count++ < 10) {
560 sync_event.Reset();
561 task_queue.PostTask([this, &last_decoded_frame_num, &sync_event]() {
562 last_decoded_frame_num = processor_->LastDecodedFrameNumber();
563 sync_event.Set();
564 });
565 sync_event.Wait(rtc::Event::kForever);
566
567 SleepMs(1000);
568 }
569 EXPECT_LT(wait_count, 10) << "Lost frames in the VideoProcessor.";
570 }
571
572 ReleaseAndCloseObjects(&task_queue);
573
574 // Verify QP parsing.
575 // TODO(brandtr): This verification is somewhat orthogonal to the rest of
576 // this test, which is focused on measuring image quality and rate control
577 // quality. We should create a whole separate test that verifies the QP
578 // parsing. This could be done by instantiating a VideoProcessor, encoding
579 // a number of frames, and then verifying the parsing.
580 if (!config_.hw_codec &&
581 (config_.codec_settings.codecType == kVideoCodecVP8 ||
582 config_.codec_settings.codecType == kVideoCodecVP9)) {
583 for (int frame_number = 0; frame_number < num_frames; ++frame_number) {
584 task_queue.PostTask([this, frame_number] {
585 EXPECT_EQ(processor_->GetQpFromEncoder(frame_number),
586 processor_->GetQpFromBitstream(frame_number));
587 });
588 }
589 }
590
591 // Calculate and print rate control statistics.
592 rate_update_index = 0;
593 frame_number = 0;
594 UpdateRates(rate_update_index, rate_profile);
595 ResetRateControlMetrics(
596 rate_profile.frame_index_rate_update[rate_update_index + 1]);
480 target_size_key_frame_initial_ = 597 target_size_key_frame_initial_ =
481 0.5 * kInitialBufferSize * bitrate_layer_[0]; 598 0.5 * kInitialBufferSize * bitrate_layer_[0];
482 processor_->SetRates(bitrate_kbps_, framerate_); 599 std::vector<int> num_dropped_frames;
600 std::vector<int> num_resize_actions;
601 sync_event.Reset();
602 task_queue.PostTask(
603 [this, &num_dropped_frames, &num_resize_actions, &sync_event]() {
604 num_dropped_frames = processor_->NumberDroppedFramesPerRateUpdate();
605 num_resize_actions = processor_->NumberSpatialResizesPerRateUpdate();
606 sync_event.Set();
607 });
608 sync_event.Wait(rtc::Event::kForever);
609 while (frame_number < num_frames) {
610 ++num_frames_per_update_[TemporalLayerIndexForFrame(frame_number)];
611 ++num_frames_total_;
612 UpdateRateControlMetrics(frame_number);
483 613
484 // Process each frame, up to |num_frames|. 614 ++frame_number;
485 int frame_number = 0;
486 int update_index = 0;
487 int num_frames = rate_profile.num_frames;
488 ResetRateControlMetrics(
489 rate_profile.frame_index_rate_update[update_index + 1]);
490 615
491 if (config_.batch_mode) { 616 if (frame_number ==
492 // In batch mode, we calculate the metrics for all frames after all frames 617 rate_profile.frame_index_rate_update[rate_update_index + 1]) {
493 // have been sent for encoding. 618 PrintAndMaybeVerifyRateControlMetrics(rate_update_index, rc_thresholds,
619 num_dropped_frames,
620 num_resize_actions);
621 ++rate_update_index;
622 UpdateRates(rate_update_index, rate_profile);
623 ResetRateControlMetrics(
624 rate_profile.frame_index_rate_update[rate_update_index + 1]);
625 }
626 }
627 PrintAndMaybeVerifyRateControlMetrics(rate_update_index, rc_thresholds,
628 num_dropped_frames,
629 num_resize_actions);
494 630
495 // TODO(brandtr): Refactor "frame number accounting" so we don't have to 631 // Calculate and print other statistics.
496 // call ProcessFrame num_frames+1 times here. 632 EXPECT_EQ(num_frames, static_cast<int>(stats_.stats_.size()));
497 for (frame_number = 0; frame_number <= num_frames; ++frame_number) { 633 stats_.PrintSummary();
498 processor_->ProcessFrame(frame_number);
499 }
500 634
501 for (frame_number = 0; frame_number < num_frames; ++frame_number) { 635 // Calculate and print image quality statistics.
502 const int tl_idx = TemporalLayerIndexForFrame(frame_number);
503 ++num_frames_per_update_[tl_idx];
504 ++num_frames_total_;
505 UpdateRateControlMetrics(frame_number);
506 }
507 } else {
508 // In online mode, we calculate the metrics for a given frame right after
509 // it has been sent for encoding.
510
511 if (config_.hw_codec) {
512 LOG(LS_WARNING) << "HW codecs should mostly be run in batch mode, "
513 "since they may be pipelining.";
514 }
515
516 while (frame_number < num_frames) {
517 processor_->ProcessFrame(frame_number);
518 VerifyQpParser(frame_number);
519 const int tl_idx = TemporalLayerIndexForFrame(frame_number);
520 ++num_frames_per_update_[tl_idx];
521 ++num_frames_total_;
522 UpdateRateControlMetrics(frame_number);
523
524 ++frame_number;
525
526 // If we hit another/next update, verify stats for current state and
527 // update layers and codec with new rates.
528 if (frame_number ==
529 rate_profile.frame_index_rate_update[update_index + 1]) {
530 VerifyRateControlMetrics(update_index, rc_thresholds[update_index]);
531
532 // Update layer rates and the codec with new rates.
533 ++update_index;
534 bitrate_kbps_ = rate_profile.target_bit_rate[update_index];
535 framerate_ = rate_profile.input_frame_rate[update_index];
536 SetTemporalLayerRates();
537 ResetRateControlMetrics(
538 rate_profile.frame_index_rate_update[update_index + 1]);
539 processor_->SetRates(bitrate_kbps_, framerate_);
540 }
541 }
542 // TODO(brandtr): Refactor "frame number accounting" so we don't have to
543 // call ProcessFrame one extra time here.
544 processor_->ProcessFrame(frame_number);
545 }
546
547 // Verify rate control metrics for all frames (if in batch mode), or for all
548 // frames since the last rate update (if not in batch mode).
549 VerifyRateControlMetrics(update_index, rc_thresholds[update_index]);
550 EXPECT_EQ(num_frames, frame_number);
551 EXPECT_EQ(num_frames + 1, static_cast<int>(stats_.stats_.size()));
552
553 // Release encoder and decoder to make sure they have finished processing.
554 processor_->Release();
555 DestroyEncoderAndDecoder();
556
557 // Close the analysis files before we use them for SSIM/PSNR calculations.
558 analysis_frame_reader_->Close();
559 analysis_frame_writer_->Close();
560
561 // Close visualization files.
562 if (encoded_frame_writer_) {
563 EXPECT_TRUE(encoded_frame_writer_->Close());
564 }
565 if (decoded_frame_writer_) {
566 decoded_frame_writer_->Close();
567 }
568
569 // TODO(marpan): Should compute these quality metrics per SetRates update. 636 // TODO(marpan): Should compute these quality metrics per SetRates update.
570 QualityMetricsResult psnr_result, ssim_result; 637 QualityMetricsResult psnr_result, ssim_result;
571 EXPECT_EQ(0, I420MetricsFromFiles(config_.input_filename.c_str(), 638 EXPECT_EQ(0, I420MetricsFromFiles(config_.input_filename.c_str(),
572 config_.output_filename.c_str(), 639 config_.output_filename.c_str(),
573 config_.codec_settings.width, 640 config_.codec_settings.width,
574 config_.codec_settings.height, 641 config_.codec_settings.height,
575 &psnr_result, &ssim_result)); 642 &psnr_result, &ssim_result));
576 VerifyQuality(psnr_result, ssim_result, quality_thresholds); 643 if (quality_thresholds) {
577 stats_.PrintSummary(); 644 VerifyQuality(psnr_result, ssim_result, *quality_thresholds);
645 }
578 printf("PSNR avg: %f, min: %f\nSSIM avg: %f, min: %f\n", 646 printf("PSNR avg: %f, min: %f\nSSIM avg: %f, min: %f\n",
579 psnr_result.average, psnr_result.min, ssim_result.average, 647 psnr_result.average, psnr_result.min, ssim_result.average,
580 ssim_result.min); 648 ssim_result.min);
581 printf("\n"); 649 printf("\n");
582 650
583 // Remove analysis file. 651 // Remove analysis file.
584 if (remove(config_.output_filename.c_str()) < 0) { 652 if (remove(config_.output_filename.c_str()) < 0) {
585 fprintf(stderr, "Failed to remove temporary file!\n"); 653 fprintf(stderr, "Failed to remove temporary file!\n");
586 } 654 }
587 } 655 }
588 656
589 static void SetTestConfig(TestConfig* config, 657 static void SetTestConfig(TestConfig* config,
590 bool hw_codec, 658 bool hw_codec,
591 bool use_single_core, 659 bool use_single_core,
592 float packet_loss_probability, 660 float packet_loss_probability,
593 std::string filename, 661 std::string filename,
594 bool verbose_logging, 662 bool verbose_logging) {
595 bool batch_mode) {
596 config->filename = filename; 663 config->filename = filename;
597 config->input_filename = ResourcePath(filename, "yuv"); 664 config->input_filename = ResourcePath(filename, "yuv");
598 // Generate an output filename in a safe way. 665 // Generate an output filename in a safe way.
599 config->output_filename = 666 config->output_filename =
600 TempFilename(OutputPath(), "videoprocessor_integrationtest"); 667 TempFilename(OutputPath(), "videoprocessor_integrationtest");
601 config->networking_config.packet_loss_probability = packet_loss_probability; 668 config->networking_config.packet_loss_probability = packet_loss_probability;
602 config->use_single_core = use_single_core; 669 config->use_single_core = use_single_core;
603 config->verbose = verbose_logging; 670 config->verbose = verbose_logging;
604 config->hw_codec = hw_codec; 671 config->hw_codec = hw_codec;
605 config->batch_mode = batch_mode;
606 } 672 }
607 673
608 static void SetCodecSettings(TestConfig* config, 674 static void SetCodecSettings(TestConfig* config,
609 VideoCodecType codec_type, 675 VideoCodecType codec_type,
610 int num_temporal_layers, 676 int num_temporal_layers,
611 bool error_concealment_on, 677 bool error_concealment_on,
612 bool denoising_on, 678 bool denoising_on,
613 bool frame_dropper_on, 679 bool frame_dropper_on,
614 bool spatial_resize_on, 680 bool spatial_resize_on,
615 bool resilience_on, 681 bool resilience_on,
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
656 int rate_update_index, 722 int rate_update_index,
657 int bitrate_kbps, 723 int bitrate_kbps,
658 int framerate_fps, 724 int framerate_fps,
659 int frame_index_rate_update) { 725 int frame_index_rate_update) {
660 rate_profile->target_bit_rate[rate_update_index] = bitrate_kbps; 726 rate_profile->target_bit_rate[rate_update_index] = bitrate_kbps;
661 rate_profile->input_frame_rate[rate_update_index] = framerate_fps; 727 rate_profile->input_frame_rate[rate_update_index] = framerate_fps;
662 rate_profile->frame_index_rate_update[rate_update_index] = 728 rate_profile->frame_index_rate_update[rate_update_index] =
663 frame_index_rate_update; 729 frame_index_rate_update;
664 } 730 }
665 731
666 static void SetRateControlThresholds(RateControlThresholds* rc_thresholds, 732 static void AddRateControlThresholds(
667 int update_index, 733 int max_num_dropped_frames,
668 int max_num_dropped_frames, 734 int max_key_frame_size_mismatch,
669 int max_key_frame_size_mismatch, 735 int max_delta_frame_size_mismatch,
670 int max_delta_frame_size_mismatch, 736 int max_encoding_rate_mismatch,
671 int max_encoding_rate_mismatch, 737 int max_time_hit_target,
672 int max_time_hit_target, 738 int num_spatial_resizes,
673 int num_spatial_resizes, 739 int num_key_frames,
674 int num_key_frames) { 740 std::vector<RateControlThresholds>* rc_thresholds) {
675 rc_thresholds[update_index].max_num_dropped_frames = max_num_dropped_frames; 741 RTC_DCHECK(rc_thresholds);
676 rc_thresholds[update_index].max_key_frame_size_mismatch = 742
677 max_key_frame_size_mismatch; 743 rc_thresholds->emplace_back();
678 rc_thresholds[update_index].max_delta_frame_size_mismatch = 744 RateControlThresholds* rc_threshold = &rc_thresholds->back();
679 max_delta_frame_size_mismatch; 745 rc_threshold->max_num_dropped_frames = max_num_dropped_frames;
680 rc_thresholds[update_index].max_encoding_rate_mismatch = 746 rc_threshold->max_key_frame_size_mismatch = max_key_frame_size_mismatch;
681 max_encoding_rate_mismatch; 747 rc_threshold->max_delta_frame_size_mismatch = max_delta_frame_size_mismatch;
682 rc_thresholds[update_index].max_time_hit_target = max_time_hit_target; 748 rc_threshold->max_encoding_rate_mismatch = max_encoding_rate_mismatch;
683 rc_thresholds[update_index].num_spatial_resizes = num_spatial_resizes; 749 rc_threshold->max_time_hit_target = max_time_hit_target;
684 rc_thresholds[update_index].num_key_frames = num_key_frames; 750 rc_threshold->num_spatial_resizes = num_spatial_resizes;
751 rc_threshold->num_key_frames = num_key_frames;
685 } 752 }
686 753
687 // Config. 754 // Config.
688 TestConfig config_; 755 TestConfig config_;
689 756
690 // Codecs. 757 // Codecs.
691 std::unique_ptr<cricket::WebRtcVideoEncoderFactory> encoder_factory_; 758 std::unique_ptr<cricket::WebRtcVideoEncoderFactory> encoder_factory_;
692 VideoEncoder* encoder_; 759 VideoEncoder* encoder_;
693 std::unique_ptr<cricket::WebRtcVideoDecoderFactory> decoder_factory_; 760 std::unique_ptr<cricket::WebRtcVideoDecoderFactory> decoder_factory_;
694 VideoDecoder* decoder_; 761 VideoDecoder* decoder_;
(...skipping 27 matching lines...) Expand all
722 float target_size_key_frame_initial_; 789 float target_size_key_frame_initial_;
723 float target_size_key_frame_; 790 float target_size_key_frame_;
724 float sum_key_frame_size_mismatch_; 791 float sum_key_frame_size_mismatch_;
725 int num_key_frames_; 792 int num_key_frames_;
726 }; 793 };
727 794
728 } // namespace test 795 } // namespace test
729 } // namespace webrtc 796 } // namespace webrtc
730 797
731 #endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_INTEGRATIONTES T_H_ 798 #endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_INTEGRATIONTES T_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698