| OLD | NEW |
| 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 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 #if defined(WEBRTC_ANDROID) | 21 #if defined(WEBRTC_ANDROID) |
| 22 #include "webrtc/modules/video_coding/codecs/test/android_test_initializer.h" | 22 #include "webrtc/modules/video_coding/codecs/test/android_test_initializer.h" |
| 23 #include "webrtc/sdk/android/src/jni/androidmediadecoder_jni.h" | 23 #include "webrtc/sdk/android/src/jni/androidmediadecoder_jni.h" |
| 24 #include "webrtc/sdk/android/src/jni/androidmediaencoder_jni.h" | 24 #include "webrtc/sdk/android/src/jni/androidmediaencoder_jni.h" |
| 25 #elif defined(WEBRTC_IOS) | 25 #elif defined(WEBRTC_IOS) |
| 26 #include "webrtc/sdk/objc/Framework/Classes/VideoToolbox/decoder.h" | 26 #include "webrtc/sdk/objc/Framework/Classes/VideoToolbox/decoder.h" |
| 27 #include "webrtc/sdk/objc/Framework/Classes/VideoToolbox/encoder.h" | 27 #include "webrtc/sdk/objc/Framework/Classes/VideoToolbox/encoder.h" |
| 28 #endif | 28 #endif |
| 29 | 29 |
| 30 #include "webrtc/base/checks.h" | 30 #include "webrtc/base/checks.h" |
| 31 #include "webrtc/base/event.h" |
| 31 #include "webrtc/base/file.h" | 32 #include "webrtc/base/file.h" |
| 32 #include "webrtc/base/logging.h" | 33 #include "webrtc/base/logging.h" |
| 34 #include "webrtc/base/task_queue.h" |
| 35 #include "webrtc/base/timeutils.h" |
| 33 #include "webrtc/media/engine/webrtcvideodecoderfactory.h" | 36 #include "webrtc/media/engine/webrtcvideodecoderfactory.h" |
| 34 #include "webrtc/media/engine/webrtcvideoencoderfactory.h" | 37 #include "webrtc/media/engine/webrtcvideoencoderfactory.h" |
| 35 #include "webrtc/modules/video_coding/codecs/h264/include/h264.h" | 38 #include "webrtc/modules/video_coding/codecs/h264/include/h264.h" |
| 36 #include "webrtc/modules/video_coding/codecs/test/packet_manipulator.h" | 39 #include "webrtc/modules/video_coding/codecs/test/packet_manipulator.h" |
| 37 #include "webrtc/modules/video_coding/codecs/test/videoprocessor.h" | 40 #include "webrtc/modules/video_coding/codecs/test/videoprocessor.h" |
| 38 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h" | 41 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h" |
| 39 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h" | 42 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h" |
| 40 #include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h" | 43 #include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h" |
| 41 #include "webrtc/modules/video_coding/include/video_codec_interface.h" | 44 #include "webrtc/modules/video_coding/include/video_codec_interface.h" |
| 42 #include "webrtc/modules/video_coding/include/video_coding.h" | 45 #include "webrtc/modules/video_coding/include/video_coding.h" |
| 43 #include "webrtc/modules/video_coding/utility/ivf_file_writer.h" | 46 #include "webrtc/modules/video_coding/utility/ivf_file_writer.h" |
| 47 #include "webrtc/system_wrappers/include/sleep.h" |
| 44 #include "webrtc/test/gtest.h" | 48 #include "webrtc/test/gtest.h" |
| 45 #include "webrtc/test/testsupport/fileutils.h" | 49 #include "webrtc/test/testsupport/fileutils.h" |
| 46 #include "webrtc/test/testsupport/frame_reader.h" | 50 #include "webrtc/test/testsupport/frame_reader.h" |
| 47 #include "webrtc/test/testsupport/frame_writer.h" | 51 #include "webrtc/test/testsupport/frame_writer.h" |
| 48 #include "webrtc/test/testsupport/metrics/video_metrics.h" | 52 #include "webrtc/test/testsupport/metrics/video_metrics.h" |
| 49 #include "webrtc/test/testsupport/packet_reader.h" | 53 #include "webrtc/test/testsupport/packet_reader.h" |
| 50 #include "webrtc/typedefs.h" | 54 #include "webrtc/typedefs.h" |
| 51 | 55 |
| 52 namespace webrtc { | 56 namespace webrtc { |
| 53 namespace test { | 57 namespace test { |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 encoder_.reset(VP9Encoder::Create()); | 234 encoder_.reset(VP9Encoder::Create()); |
| 231 decoder_.reset(VP9Decoder::Create()); | 235 decoder_.reset(VP9Decoder::Create()); |
| 232 break; | 236 break; |
| 233 default: | 237 default: |
| 234 RTC_NOTREACHED(); | 238 RTC_NOTREACHED(); |
| 235 break; | 239 break; |
| 236 } | 240 } |
| 237 } | 241 } |
| 238 | 242 |
| 239 void SetUpCodecConfig(const CodecParams& process, | 243 void SetUpCodecConfig(const CodecParams& process, |
| 244 const RateProfile& rate_profile, |
| 240 const VisualizationParams* visualization_params) { | 245 const VisualizationParams* visualization_params) { |
| 241 CreateEncoderAndDecoder(process.hw_codec, process.codec_type); | 246 CreateEncoderAndDecoder(process.hw_codec, process.codec_type); |
| 242 | 247 |
| 243 // Configure input filename. | 248 // Configure input filename. |
| 244 config_.input_filename = test::ResourcePath(process.filename, "yuv"); | 249 config_.input_filename = test::ResourcePath(process.filename, "yuv"); |
| 245 if (process.verbose_logging) | 250 if (process.verbose_logging) |
| 246 printf("Filename: %s\n", process.filename.c_str()); | 251 printf("Filename: %s\n", process.filename.c_str()); |
| 247 // Generate an output filename in a safe way. | 252 // Generate an output filename in a safe way. |
| 248 config_.output_filename = test::TempFilename( | 253 config_.output_filename = test::TempFilename( |
| 249 test::OutputPath(), "videoprocessor_integrationtest"); | 254 test::OutputPath(), "videoprocessor_integrationtest"); |
| 250 | 255 |
| 251 config_.frame_length_in_bytes = | 256 config_.frame_length_in_bytes = |
| 252 CalcBufferSize(VideoType::kI420, process.width, process.height); | 257 CalcBufferSize(VideoType::kI420, process.width, process.height); |
| 253 config_.verbose = process.verbose_logging; | 258 config_.verbose = process.verbose_logging; |
| 254 config_.use_single_core = process.use_single_core; | 259 config_.use_single_core = process.use_single_core; |
| 255 // Key frame interval and packet loss are set for each test. | 260 // Key frame interval and packet loss are set for each test. |
| 256 config_.keyframe_interval = process.key_frame_interval; | 261 config_.keyframe_interval = process.key_frame_interval; |
| 257 config_.networking_config.packet_loss_probability = | 262 config_.networking_config.packet_loss_probability = |
| 258 packet_loss_probability_; | 263 process.packet_loss_probability; |
| 259 | 264 |
| 260 // Configure codec settings. | 265 // Configure codec settings. |
| 261 VideoCodingModule::Codec(process.codec_type, &codec_settings_); | 266 VideoCodingModule::Codec(process.codec_type, &codec_settings_); |
| 262 config_.codec_settings = &codec_settings_; | 267 config_.codec_settings = &codec_settings_; |
| 263 config_.codec_settings->startBitrate = start_bitrate_; | 268 float start_bitrate = rate_profile.target_bit_rate[0]; |
| 269 config_.codec_settings->startBitrate = start_bitrate; |
| 264 config_.codec_settings->width = process.width; | 270 config_.codec_settings->width = process.width; |
| 265 config_.codec_settings->height = process.height; | 271 config_.codec_settings->height = process.height; |
| 266 | 272 |
| 267 // These features may be set depending on the test. | 273 // These features may be set depending on the test. |
| 268 switch (config_.codec_settings->codecType) { | 274 switch (config_.codec_settings->codecType) { |
| 269 case kVideoCodecH264: | 275 case kVideoCodecH264: |
| 270 config_.codec_settings->H264()->frameDroppingOn = | 276 config_.codec_settings->H264()->frameDroppingOn = |
| 271 process.frame_dropper_on; | 277 process.frame_dropper_on; |
| 272 config_.codec_settings->H264()->keyFrameInterval = | 278 config_.codec_settings->H264()->keyFrameInterval = |
| 273 kBaseKeyFrameInterval; | 279 kBaseKeyFrameInterval; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 config_.codec_settings->height)); | 317 config_.codec_settings->height)); |
| 312 RTC_CHECK(analysis_frame_reader_->Init()); | 318 RTC_CHECK(analysis_frame_reader_->Init()); |
| 313 RTC_CHECK(analysis_frame_writer_->Init()); | 319 RTC_CHECK(analysis_frame_writer_->Init()); |
| 314 | 320 |
| 315 if (visualization_params) { | 321 if (visualization_params) { |
| 316 // clang-format off | 322 // clang-format off |
| 317 const std::string output_filename_base = | 323 const std::string output_filename_base = |
| 318 test::OutputPath() + process.filename + | 324 test::OutputPath() + process.filename + |
| 319 "_cd-" + CodecTypeToPayloadName(process.codec_type).value_or("") + | 325 "_cd-" + CodecTypeToPayloadName(process.codec_type).value_or("") + |
| 320 "_hw-" + std::to_string(process.hw_codec) + | 326 "_hw-" + std::to_string(process.hw_codec) + |
| 321 "_fr-" + std::to_string(start_frame_rate_) + | 327 "_br-" + std::to_string(static_cast<int>(start_bitrate)); |
| 322 "_br-" + std::to_string(static_cast<int>(start_bitrate_)); | |
| 323 // clang-format on | 328 // clang-format on |
| 329 int start_frame_rate = rate_profile.input_frame_rate[0]; |
| 324 if (visualization_params->save_source_y4m) { | 330 if (visualization_params->save_source_y4m) { |
| 325 source_frame_writer_.reset(new test::Y4mFrameWriterImpl( | 331 source_frame_writer_.reset(new test::Y4mFrameWriterImpl( |
| 326 output_filename_base + "_source.y4m", config_.codec_settings->width, | 332 output_filename_base + "_source.y4m", config_.codec_settings->width, |
| 327 config_.codec_settings->height, start_frame_rate_)); | 333 config_.codec_settings->height, start_frame_rate)); |
| 328 RTC_CHECK(source_frame_writer_->Init()); | 334 RTC_CHECK(source_frame_writer_->Init()); |
| 329 } | 335 } |
| 330 if (visualization_params->save_encoded_ivf) { | 336 if (visualization_params->save_encoded_ivf) { |
| 331 rtc::File post_encode_file = | 337 rtc::File post_encode_file = |
| 332 rtc::File::Create(output_filename_base + "_encoded.ivf"); | 338 rtc::File::Create(output_filename_base + "_encoded.ivf"); |
| 333 encoded_frame_writer_ = | 339 encoded_frame_writer_ = |
| 334 IvfFileWriter::Wrap(std::move(post_encode_file), 0); | 340 IvfFileWriter::Wrap(std::move(post_encode_file), 0); |
| 335 } | 341 } |
| 336 if (visualization_params->save_decoded_y4m) { | 342 if (visualization_params->save_decoded_y4m) { |
| 337 decoded_frame_writer_.reset(new test::Y4mFrameWriterImpl( | 343 decoded_frame_writer_.reset(new test::Y4mFrameWriterImpl( |
| 338 output_filename_base + "_decoded.y4m", | 344 output_filename_base + "_decoded.y4m", |
| 339 config_.codec_settings->width, config_.codec_settings->height, | 345 config_.codec_settings->width, config_.codec_settings->height, |
| 340 start_frame_rate_)); | 346 start_frame_rate)); |
| 341 RTC_CHECK(decoded_frame_writer_->Init()); | 347 RTC_CHECK(decoded_frame_writer_->Init()); |
| 342 } | 348 } |
| 343 } | 349 } |
| 344 | 350 |
| 345 packet_manipulator_.reset(new test::PacketManipulatorImpl( | 351 packet_manipulator_.reset(new test::PacketManipulatorImpl( |
| 346 &packet_reader_, config_.networking_config, config_.verbose)); | 352 &packet_reader_, config_.networking_config, config_.verbose)); |
| 347 processor_.reset(new test::VideoProcessorImpl( | 353 processor_.reset(new test::VideoProcessorImpl( |
| 348 encoder_.get(), decoder_.get(), analysis_frame_reader_.get(), | 354 encoder_.get(), decoder_.get(), analysis_frame_reader_.get(), |
| 349 analysis_frame_writer_.get(), packet_manipulator_.get(), config_, | 355 analysis_frame_writer_.get(), packet_manipulator_.get(), config_, |
| 350 &stats_, source_frame_writer_.get(), encoded_frame_writer_.get(), | 356 &stats_, source_frame_writer_.get(), encoded_frame_writer_.get(), |
| 351 decoded_frame_writer_.get())); | 357 decoded_frame_writer_.get())); |
| 352 processor_->Init(); | |
| 353 } | 358 } |
| 354 | 359 |
| 355 // Reset quantities after each encoder update, update the target | 360 // Reset quantities after each encoder update, update the target |
| 356 // per-frame bandwidth. | 361 // per-frame bandwidth. |
| 357 void ResetRateControlMetrics(int num_frames_to_hit_target) { | 362 void ResetRateControlMetrics(int num_frames_to_hit_target) { |
| 358 for (int i = 0; i < num_temporal_layers_; i++) { | 363 for (int i = 0; i < num_temporal_layers_; i++) { |
| 359 num_frames_per_update_[i] = 0; | 364 num_frames_per_update_[i] = 0; |
| 360 sum_frame_size_mismatch_[i] = 0.0f; | 365 sum_frame_size_mismatch_[i] = 0.0f; |
| 361 sum_encoded_frame_size_[i] = 0.0f; | 366 sum_encoded_frame_size_[i] = 0.0f; |
| 362 encoding_bitrate_[i] = 0.0f; | 367 encoding_bitrate_[i] = 0.0f; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 376 sum_encoded_frame_size_total_ = 0.0f; | 381 sum_encoded_frame_size_total_ = 0.0f; |
| 377 encoding_bitrate_total_ = 0.0f; | 382 encoding_bitrate_total_ = 0.0f; |
| 378 perc_encoding_rate_mismatch_ = 0.0f; | 383 perc_encoding_rate_mismatch_ = 0.0f; |
| 379 num_frames_to_hit_target_ = num_frames_to_hit_target; | 384 num_frames_to_hit_target_ = num_frames_to_hit_target; |
| 380 encoding_rate_within_target_ = false; | 385 encoding_rate_within_target_ = false; |
| 381 sum_key_frame_size_mismatch_ = 0.0; | 386 sum_key_frame_size_mismatch_ = 0.0; |
| 382 num_key_frames_ = 0; | 387 num_key_frames_ = 0; |
| 383 } | 388 } |
| 384 | 389 |
| 385 // For every encoded frame, update the rate control metrics. | 390 // For every encoded frame, update the rate control metrics. |
| 386 void UpdateRateControlMetrics(int frame_number) { | 391 void UpdateRateControlMetrics(int frame_number, |
| 392 FrameType frame_type, |
| 393 size_t encoded_frame_size) { |
| 387 RTC_CHECK_GE(frame_number, 0); | 394 RTC_CHECK_GE(frame_number, 0); |
| 388 int tl_idx = TemporalLayerIndexForFrame(frame_number); | 395 int tl_idx = TemporalLayerIndexForFrame(frame_number); |
| 389 FrameType frame_type = processor_->EncodedFrameType(frame_number); | 396 float encoded_size_kbits = encoded_frame_size * 8.0f / 1000.0f; |
| 390 float encoded_size_kbits = | |
| 391 processor_->EncodedFrameSize(frame_number) * 8.0f / 1000.0f; | |
| 392 | 397 |
| 393 // Update layer data. | 398 // Update layer data. |
| 394 // Update rate mismatch relative to per-frame bandwidth for delta frames. | 399 // Update rate mismatch relative to per-frame bandwidth for delta frames. |
| 395 if (frame_type == kVideoFrameDelta) { | 400 if (frame_type == kVideoFrameDelta) { |
| 396 // TODO(marpan): Should we count dropped (zero size) frames in mismatch? | 401 // TODO(marpan): Should we count dropped (zero size) frames in mismatch? |
| 397 sum_frame_size_mismatch_[tl_idx] += | 402 sum_frame_size_mismatch_[tl_idx] += |
| 398 fabs(encoded_size_kbits - per_frame_bandwidth_[tl_idx]) / | 403 fabs(encoded_size_kbits - per_frame_bandwidth_[tl_idx]) / |
| 399 per_frame_bandwidth_[tl_idx]; | 404 per_frame_bandwidth_[tl_idx]; |
| 400 } else { | 405 } else { |
| 401 float target_size = (frame_number == 0) ? target_size_key_frame_initial_ | 406 float target_size = (frame_number == 0) ? target_size_key_frame_initial_ |
| (...skipping 14 matching lines...) Expand all Loading... |
| 416 sum_encoded_frame_size_total_ * frame_rate_ / num_frames_total_; | 421 sum_encoded_frame_size_total_ * frame_rate_ / num_frames_total_; |
| 417 perc_encoding_rate_mismatch_ = | 422 perc_encoding_rate_mismatch_ = |
| 418 100 * fabs(encoding_bitrate_total_ - bit_rate_) / bit_rate_; | 423 100 * fabs(encoding_bitrate_total_ - bit_rate_) / bit_rate_; |
| 419 if (perc_encoding_rate_mismatch_ < kPercTargetvsActualMismatch && | 424 if (perc_encoding_rate_mismatch_ < kPercTargetvsActualMismatch && |
| 420 !encoding_rate_within_target_) { | 425 !encoding_rate_within_target_) { |
| 421 num_frames_to_hit_target_ = num_frames_total_; | 426 num_frames_to_hit_target_ = num_frames_total_; |
| 422 encoding_rate_within_target_ = true; | 427 encoding_rate_within_target_ = true; |
| 423 } | 428 } |
| 424 } | 429 } |
| 425 | 430 |
| 431 void UpdateRateControlMetrics(int frame_number, rtc::TaskQueue* task_queue) { |
| 432 FrameType frame_type; |
| 433 size_t encoded_frame_size; |
| 434 |
| 435 if (task_queue) { |
| 436 rtc::Event sync_event(false, false); |
| 437 task_queue->PostTask([this, &frame_type, &encoded_frame_size, |
| 438 frame_number, &sync_event]() { |
| 439 frame_type = processor_->EncodedFrameType(frame_number); |
| 440 encoded_frame_size = processor_->EncodedFrameSize(frame_number); |
| 441 sync_event.Set(); |
| 442 }); |
| 443 ASSERT_TRUE(sync_event.Wait(rtc::Event::kForever)); |
| 444 } else { |
| 445 frame_type = processor_->EncodedFrameType(frame_number); |
| 446 encoded_frame_size = processor_->EncodedFrameSize(frame_number); |
| 447 } |
| 448 |
| 449 UpdateRateControlMetrics(frame_number, frame_type, encoded_frame_size); |
| 450 } |
| 451 |
| 452 void UpdateRateControlMetrics(int frame_number) { |
| 453 UpdateRateControlMetrics(frame_number, nullptr); |
| 454 } |
| 455 |
| 426 // Verify expected behavior of rate control and print out data. | 456 // Verify expected behavior of rate control and print out data. |
| 427 void VerifyRateControlMetrics(int update_index, | 457 void VerifyRateControlMetrics(int update_index, |
| 428 const RateControlThresholds& rc_expected) { | 458 const RateControlThresholds& rc_expected, |
| 429 int num_dropped_frames = processor_->NumberDroppedFrames(); | 459 int num_dropped_frames, |
| 430 int num_resize_actions = processor_->NumberSpatialResizes(); | 460 int num_resize_actions) { |
| 431 printf( | 461 printf( |
| 432 "For update #: %d,\n" | 462 "For update #: %d,\n" |
| 433 " Target Bitrate: %d,\n" | 463 " Target Bitrate: %d,\n" |
| 434 " Encoding bitrate: %f,\n" | 464 " Encoding bitrate: %f,\n" |
| 435 " Frame rate: %d \n", | 465 " Frame rate: %d \n", |
| 436 update_index, bit_rate_, encoding_bitrate_total_, frame_rate_); | 466 update_index, bit_rate_, encoding_bitrate_total_, frame_rate_); |
| 437 printf( | 467 printf( |
| 438 " Number of processed frames: %d, \n" | 468 " Number of processed frames: %d, \n" |
| 439 " Number of frames to approach target rate: %d, \n" | 469 " Number of frames to approach target rate: %d, \n" |
| 440 " Number of dropped frames: %d, \n" | 470 " Number of dropped frames: %d, \n" |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 482 EXPECT_LE(num_frames_to_hit_target_, rc_expected.max_time_hit_target); | 512 EXPECT_LE(num_frames_to_hit_target_, rc_expected.max_time_hit_target); |
| 483 EXPECT_LE(num_dropped_frames, rc_expected.max_num_dropped_frames); | 513 EXPECT_LE(num_dropped_frames, rc_expected.max_num_dropped_frames); |
| 484 if (rc_expected.num_spatial_resizes >= 0) { | 514 if (rc_expected.num_spatial_resizes >= 0) { |
| 485 EXPECT_EQ(rc_expected.num_spatial_resizes, num_resize_actions); | 515 EXPECT_EQ(rc_expected.num_spatial_resizes, num_resize_actions); |
| 486 } | 516 } |
| 487 if (rc_expected.num_key_frames >= 0) { | 517 if (rc_expected.num_key_frames >= 0) { |
| 488 EXPECT_EQ(rc_expected.num_key_frames, num_key_frames_); | 518 EXPECT_EQ(rc_expected.num_key_frames, num_key_frames_); |
| 489 } | 519 } |
| 490 } | 520 } |
| 491 | 521 |
| 522 void VerifyRateControlMetrics(int update_index, |
| 523 const RateControlThresholds& rc_expected, |
| 524 rtc::TaskQueue* task_queue) { |
| 525 int num_dropped_frames; |
| 526 int num_resize_actions; |
| 527 |
| 528 if (task_queue) { |
| 529 rtc::Event sync_event(false, false); |
| 530 task_queue->PostTask( |
| 531 [this, &num_dropped_frames, &num_resize_actions, &sync_event]() { |
| 532 num_dropped_frames = processor_->NumberDroppedFrames(); |
| 533 num_resize_actions = processor_->NumberSpatialResizes(); |
| 534 sync_event.Set(); |
| 535 }); |
| 536 ASSERT_TRUE(sync_event.Wait(rtc::Event::kForever)); |
| 537 } else { |
| 538 num_dropped_frames = processor_->NumberDroppedFrames(); |
| 539 num_resize_actions = processor_->NumberSpatialResizes(); |
| 540 } |
| 541 |
| 542 VerifyRateControlMetrics(update_index, rc_expected, num_dropped_frames, |
| 543 num_resize_actions); |
| 544 } |
| 545 |
| 546 void VerifyRateControlMetrics(int update_index, |
| 547 const RateControlThresholds& rc_expected) { |
| 548 VerifyRateControlMetrics(update_index, rc_expected, nullptr); |
| 549 } |
| 550 |
| 492 void VerifyQuality(const test::QualityMetricsResult& psnr_result, | 551 void VerifyQuality(const test::QualityMetricsResult& psnr_result, |
| 493 const test::QualityMetricsResult& ssim_result, | 552 const test::QualityMetricsResult& ssim_result, |
| 494 const QualityThresholds& quality_thresholds) { | 553 const QualityThresholds& quality_thresholds) { |
| 495 EXPECT_GT(psnr_result.average, quality_thresholds.min_avg_psnr); | 554 EXPECT_GT(psnr_result.average, quality_thresholds.min_avg_psnr); |
| 496 EXPECT_GT(psnr_result.min, quality_thresholds.min_min_psnr); | 555 EXPECT_GT(psnr_result.min, quality_thresholds.min_min_psnr); |
| 497 EXPECT_GT(ssim_result.average, quality_thresholds.min_avg_ssim); | 556 EXPECT_GT(ssim_result.average, quality_thresholds.min_avg_ssim); |
| 498 EXPECT_GT(ssim_result.min, quality_thresholds.min_min_ssim); | 557 EXPECT_GT(ssim_result.min, quality_thresholds.min_min_ssim); |
| 499 } | 558 } |
| 500 | 559 |
| 501 void VerifyQpParser(const CodecParams& process, int frame_number) { | 560 void VerifyQpParser(const CodecParams& process, int frame_number) { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 563 // TODO(brandtr): Change the second last argument to be a | 622 // TODO(brandtr): Change the second last argument to be a |
| 564 // const std::vector<RateControlThresholds>&, so we can ensure that the user | 623 // const std::vector<RateControlThresholds>&, so we can ensure that the user |
| 565 // does not expect us to do mid-clip rate updates when we are not able to, | 624 // does not expect us to do mid-clip rate updates when we are not able to, |
| 566 // e.g., when we are operating in batch mode. | 625 // e.g., when we are operating in batch mode. |
| 567 void ProcessFramesAndVerify(QualityThresholds quality_thresholds, | 626 void ProcessFramesAndVerify(QualityThresholds quality_thresholds, |
| 568 RateProfile rate_profile, | 627 RateProfile rate_profile, |
| 569 CodecParams process, | 628 CodecParams process, |
| 570 RateControlThresholds* rc_thresholds, | 629 RateControlThresholds* rc_thresholds, |
| 571 const VisualizationParams* visualization_params) { | 630 const VisualizationParams* visualization_params) { |
| 572 // Codec/config settings. | 631 // Codec/config settings. |
| 573 start_bitrate_ = rate_profile.target_bit_rate[0]; | |
| 574 start_frame_rate_ = rate_profile.input_frame_rate[0]; | |
| 575 packet_loss_probability_ = process.packet_loss_probability; | |
| 576 num_temporal_layers_ = process.num_temporal_layers; | 632 num_temporal_layers_ = process.num_temporal_layers; |
| 577 SetUpCodecConfig(process, visualization_params); | 633 SetUpCodecConfig(process, rate_profile, visualization_params); |
| 634 |
| 578 // Update the temporal layers and the codec with the initial rates. | 635 // Update the temporal layers and the codec with the initial rates. |
| 579 bit_rate_ = rate_profile.target_bit_rate[0]; | 636 bit_rate_ = rate_profile.target_bit_rate[0]; |
| 580 frame_rate_ = rate_profile.input_frame_rate[0]; | 637 frame_rate_ = rate_profile.input_frame_rate[0]; |
| 581 SetTemporalLayerRates(); | 638 SetTemporalLayerRates(); |
| 582 // Set the initial target size for key frame. | 639 // Set the initial target size for key frame. |
| 583 target_size_key_frame_initial_ = | 640 target_size_key_frame_initial_ = |
| 584 0.5 * kInitialBufferSize * bit_rate_layer_[0]; | 641 0.5 * kInitialBufferSize * bit_rate_layer_[0]; |
| 585 processor_->SetRates(bit_rate_, frame_rate_); | |
| 586 | 642 |
| 587 // Process each frame, up to |num_frames|. | 643 // Process each frame, up to |num_frames|. |
| 588 int frame_number = 0; | 644 int frame_number = 0; |
| 589 int update_index = 0; | 645 int update_index = 0; |
| 590 int num_frames = rate_profile.num_frames; | 646 int num_frames = rate_profile.num_frames; |
| 591 ResetRateControlMetrics( | 647 ResetRateControlMetrics( |
| 592 rate_profile.frame_index_rate_update[update_index + 1]); | 648 rate_profile.frame_index_rate_update[update_index + 1]); |
| 593 | 649 |
| 594 if (process.batch_mode) { | 650 if (process.batch_mode) { |
| 595 // In batch mode, we calculate the metrics for all frames after all frames | 651 // In batch mode, we calculate the metrics for all frames after all frames |
| 596 // have been sent for encoding. | 652 // have been sent for encoding. |
| 597 | 653 |
| 654 // AndroidMediaEncoder must be called on a task queue, so during the batch |
| 655 // run we will call |processor_| on a task queue. |
| 656 rtc::TaskQueue task_queue("VidProc TQ"); |
| 657 |
| 658 // Initialize |processor_|, which initializes the encoder and decoder. |
| 659 rtc::Event sync_event(false, false); |
| 660 task_queue.PostTask([this, &sync_event]() { |
| 661 processor_->Init(); |
| 662 processor_->SetRates(bit_rate_, frame_rate_); |
| 663 sync_event.Set(); |
| 664 }); |
| 665 ASSERT_TRUE(sync_event.Wait(rtc::Event::kForever)); |
| 666 |
| 667 // Post all frames (in order) to encoder. |
| 668 int start_frame_rate = rate_profile.input_frame_rate[0]; |
| 598 // TODO(brandtr): Refactor "frame number accounting" so we don't have to | 669 // TODO(brandtr): Refactor "frame number accounting" so we don't have to |
| 599 // call ProcessFrame num_frames+1 times here. | 670 // call ProcessFrame num_frames+1 times here. |
| 600 for (frame_number = 0; frame_number <= num_frames; ++frame_number) { | 671 for (frame_number = 0; frame_number <= num_frames; ++frame_number) { |
| 601 EXPECT_TRUE(processor_->ProcessFrame(frame_number)); | 672 task_queue.PostTask([this, frame_number]() { |
| 673 EXPECT_TRUE(processor_->ProcessFrame(frame_number)); |
| 674 }); |
| 675 |
| 676 // In order to not overwhelm the OpenMAX buffers in the Android |
| 677 // MediaCodec API, we roughly pace the frames here. The downside |
| 678 // is that the encode run will be done in realtime. |
| 679 if (process.hw_codec) { |
| 680 SleepMs(rtc::kNumMillisecsPerSec / start_frame_rate); |
| 681 } |
| 602 } | 682 } |
| 603 | 683 |
| 684 // Give the task queue some time to finish processing the posted frames, |
| 685 // then shut down processing and synchronize with main thread. |
| 686 SleepMs(rtc::kNumMillisecsPerSec); |
| 687 sync_event.Reset(); |
| 688 task_queue.PostTask([this, &sync_event]() { |
| 689 processor_->Release(); |
| 690 sync_event.Set(); |
| 691 }); |
| 692 ASSERT_TRUE(sync_event.Wait(rtc::Event::kForever)); |
| 693 |
| 694 // Calculate and print rate control metrics. |
| 604 for (frame_number = 0; frame_number < num_frames; ++frame_number) { | 695 for (frame_number = 0; frame_number < num_frames; ++frame_number) { |
| 605 ++num_frames_per_update_[TemporalLayerIndexForFrame(frame_number)]; | 696 ++num_frames_per_update_[TemporalLayerIndexForFrame(frame_number)]; |
| 606 ++num_frames_total_; | 697 ++num_frames_total_; |
| 607 UpdateRateControlMetrics(frame_number); | 698 UpdateRateControlMetrics(frame_number, &task_queue); |
| 608 } | 699 } |
| 700 |
| 701 VerifyRateControlMetrics(update_index, rc_thresholds[0], &task_queue); |
| 609 } else { | 702 } else { |
| 610 // In online mode, we calculate the metrics for a given frame right after | 703 // In online mode, we calculate the metrics for a given frame right after |
| 611 // it has been sent for encoding. | 704 // it has been sent for encoding. |
| 612 | 705 |
| 613 if (process.hw_codec) { | 706 if (process.hw_codec) { |
| 614 LOG(LS_WARNING) << "HW codecs should mostly be run in batch mode, " | 707 LOG(LS_WARNING) << "HW codecs should mostly be run in batch mode, " |
| 615 "since they may be pipelining."; | 708 "since they may be pipelining."; |
| 616 } | 709 } |
| 617 | 710 |
| 711 // Initialize |processor_| on main thread. |
| 712 processor_->Init(); |
| 713 processor_->SetRates(bit_rate_, frame_rate_); |
| 714 |
| 618 while (frame_number < num_frames) { | 715 while (frame_number < num_frames) { |
| 619 EXPECT_TRUE(processor_->ProcessFrame(frame_number)); | 716 EXPECT_TRUE(processor_->ProcessFrame(frame_number)); |
| 620 VerifyQpParser(process, frame_number); | 717 VerifyQpParser(process, frame_number); |
| 621 ++num_frames_per_update_[TemporalLayerIndexForFrame(frame_number)]; | 718 ++num_frames_per_update_[TemporalLayerIndexForFrame(frame_number)]; |
| 622 ++num_frames_total_; | 719 ++num_frames_total_; |
| 623 UpdateRateControlMetrics(frame_number); | 720 UpdateRateControlMetrics(frame_number); |
| 624 | 721 |
| 625 ++frame_number; | 722 ++frame_number; |
| 626 | 723 |
| 627 // If we hit another/next update, verify stats for current state and | 724 // If we hit another/next update, verify stats for current state and |
| 628 // update layers and codec with new rates. | 725 // update layers and codec with new rates. |
| 629 if (frame_number == | 726 if (frame_number == |
| 630 rate_profile.frame_index_rate_update[update_index + 1]) { | 727 rate_profile.frame_index_rate_update[update_index + 1]) { |
| 631 VerifyRateControlMetrics(update_index, rc_thresholds[update_index]); | 728 VerifyRateControlMetrics(update_index, rc_thresholds[update_index]); |
| 632 | 729 |
| 633 // Update layer rates and the codec with new rates. | 730 // Update layer rates and the codec with new rates. |
| 634 ++update_index; | 731 ++update_index; |
| 635 bit_rate_ = rate_profile.target_bit_rate[update_index]; | 732 bit_rate_ = rate_profile.target_bit_rate[update_index]; |
| 636 frame_rate_ = rate_profile.input_frame_rate[update_index]; | 733 frame_rate_ = rate_profile.input_frame_rate[update_index]; |
| 637 SetTemporalLayerRates(); | 734 SetTemporalLayerRates(); |
| 638 ResetRateControlMetrics( | 735 ResetRateControlMetrics( |
| 639 rate_profile.frame_index_rate_update[update_index + 1]); | 736 rate_profile.frame_index_rate_update[update_index + 1]); |
| 640 processor_->SetRates(bit_rate_, frame_rate_); | 737 processor_->SetRates(bit_rate_, frame_rate_); |
| 641 } | 738 } |
| 642 } | 739 } |
| 643 // TODO(brandtr): Refactor "frame number accounting" so we don't have to | 740 // TODO(brandtr): Refactor "frame number accounting" so we don't have to |
| 644 // call ProcessFrame one extra time here. | 741 // call ProcessFrame one extra time here. |
| 645 EXPECT_TRUE(processor_->ProcessFrame(frame_number)); | 742 EXPECT_TRUE(processor_->ProcessFrame(frame_number)); |
| 743 |
| 744 // Release codecs to make sure they have finished processing. |
| 745 processor_->Release(); |
| 746 |
| 747 // Verify for final rate update. |
| 748 VerifyRateControlMetrics(update_index, rc_thresholds[update_index]); |
| 646 } | 749 } |
| 647 | |
| 648 // Verify rate control metrics for all frames (if in batch mode), or for all | |
| 649 // frames since the last rate update (if not in batch mode). | |
| 650 VerifyRateControlMetrics(update_index, rc_thresholds[update_index]); | |
| 651 EXPECT_EQ(num_frames, frame_number); | 750 EXPECT_EQ(num_frames, frame_number); |
| 652 EXPECT_EQ(num_frames + 1, static_cast<int>(stats_.stats_.size())); | 751 EXPECT_EQ(num_frames + 1, static_cast<int>(stats_.stats_.size())); |
| 653 | 752 |
| 654 // Release encoder and decoder to make sure they have finished processing. | |
| 655 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->Release()); | |
| 656 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->Release()); | |
| 657 | |
| 658 // Close the analysis files before we use them for SSIM/PSNR calculations. | 753 // Close the analysis files before we use them for SSIM/PSNR calculations. |
| 659 analysis_frame_reader_->Close(); | 754 analysis_frame_reader_->Close(); |
| 660 analysis_frame_writer_->Close(); | 755 analysis_frame_writer_->Close(); |
| 661 | 756 |
| 662 // Close visualization files. | 757 // Close visualization files. |
| 663 if (source_frame_writer_) { | 758 if (source_frame_writer_) { |
| 664 source_frame_writer_->Close(); | 759 source_frame_writer_->Close(); |
| 665 } | 760 } |
| 666 if (encoded_frame_writer_) { | 761 if (encoded_frame_writer_) { |
| 667 EXPECT_TRUE(encoded_frame_writer_->Close()); | 762 EXPECT_TRUE(encoded_frame_writer_->Close()); |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 822 float encoding_bitrate_total_; | 917 float encoding_bitrate_total_; |
| 823 float perc_encoding_rate_mismatch_; | 918 float perc_encoding_rate_mismatch_; |
| 824 int num_frames_to_hit_target_; | 919 int num_frames_to_hit_target_; |
| 825 bool encoding_rate_within_target_; | 920 bool encoding_rate_within_target_; |
| 826 int bit_rate_; | 921 int bit_rate_; |
| 827 int frame_rate_; | 922 int frame_rate_; |
| 828 float target_size_key_frame_initial_; | 923 float target_size_key_frame_initial_; |
| 829 float target_size_key_frame_; | 924 float target_size_key_frame_; |
| 830 float sum_key_frame_size_mismatch_; | 925 float sum_key_frame_size_mismatch_; |
| 831 int num_key_frames_; | 926 int num_key_frames_; |
| 832 float start_bitrate_; | |
| 833 int start_frame_rate_; | |
| 834 | 927 |
| 835 // Codec and network settings. | 928 // Codec and network settings. |
| 836 float packet_loss_probability_; | |
| 837 int num_temporal_layers_; | 929 int num_temporal_layers_; |
| 838 }; | 930 }; |
| 839 | 931 |
| 840 } // namespace test | 932 } // namespace test |
| 841 } // namespace webrtc | 933 } // namespace webrtc |
| 842 | 934 |
| 843 #endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_INTEGRATIONTES
T_H_ | 935 #endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_INTEGRATIONTES
T_H_ |
| OLD | NEW |