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 20 matching lines...) Expand all Loading... | |
31 #include "webrtc/media/engine/internalencoderfactory.h" | 31 #include "webrtc/media/engine/internalencoderfactory.h" |
32 #include "webrtc/media/engine/webrtcvideodecoderfactory.h" | 32 #include "webrtc/media/engine/webrtcvideodecoderfactory.h" |
33 #include "webrtc/media/engine/webrtcvideoencoderfactory.h" | 33 #include "webrtc/media/engine/webrtcvideoencoderfactory.h" |
34 #include "webrtc/modules/video_coding/codecs/test/packet_manipulator.h" | 34 #include "webrtc/modules/video_coding/codecs/test/packet_manipulator.h" |
35 #include "webrtc/modules/video_coding/codecs/test/videoprocessor.h" | 35 #include "webrtc/modules/video_coding/codecs/test/videoprocessor.h" |
36 #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" |
37 #include "webrtc/modules/video_coding/include/video_codec_interface.h" | 37 #include "webrtc/modules/video_coding/include/video_codec_interface.h" |
38 #include "webrtc/modules/video_coding/include/video_coding.h" | 38 #include "webrtc/modules/video_coding/include/video_coding.h" |
39 #include "webrtc/modules/video_coding/utility/ivf_file_writer.h" | 39 #include "webrtc/modules/video_coding/utility/ivf_file_writer.h" |
40 #include "webrtc/rtc_base/checks.h" | 40 #include "webrtc/rtc_base/checks.h" |
41 #include "webrtc/rtc_base/event.h" | |
41 #include "webrtc/rtc_base/file.h" | 42 #include "webrtc/rtc_base/file.h" |
42 #include "webrtc/rtc_base/logging.h" | 43 #include "webrtc/rtc_base/logging.h" |
43 #include "webrtc/rtc_base/ptr_util.h" | 44 #include "webrtc/rtc_base/ptr_util.h" |
45 #include "webrtc/system_wrappers/include/sleep.h" | |
44 #include "webrtc/test/gtest.h" | 46 #include "webrtc/test/gtest.h" |
45 #include "webrtc/test/testsupport/fileutils.h" | 47 #include "webrtc/test/testsupport/fileutils.h" |
46 #include "webrtc/test/testsupport/frame_reader.h" | 48 #include "webrtc/test/testsupport/frame_reader.h" |
47 #include "webrtc/test/testsupport/frame_writer.h" | 49 #include "webrtc/test/testsupport/frame_writer.h" |
48 #include "webrtc/test/testsupport/metrics/video_metrics.h" | 50 #include "webrtc/test/testsupport/metrics/video_metrics.h" |
49 #include "webrtc/test/testsupport/packet_reader.h" | 51 #include "webrtc/test/testsupport/packet_reader.h" |
50 #include "webrtc/test/video_codec_settings.h" | 52 #include "webrtc/test/video_codec_settings.h" |
51 #include "webrtc/typedefs.h" | 53 #include "webrtc/typedefs.h" |
52 | 54 |
53 namespace webrtc { | 55 namespace webrtc { |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 18 matching lines...) Expand all Loading... | |
216 if (visualization_params->save_decoded_y4m) { | 219 if (visualization_params->save_decoded_y4m) { |
217 decoded_frame_writer_.reset(new Y4mFrameWriterImpl( | 220 decoded_frame_writer_.reset(new Y4mFrameWriterImpl( |
218 output_filename_base + ".y4m", config_.codec_settings.width, | 221 output_filename_base + ".y4m", config_.codec_settings.width, |
219 config_.codec_settings.height, initial_framerate_fps)); | 222 config_.codec_settings.height, initial_framerate_fps)); |
220 EXPECT_TRUE(decoded_frame_writer_->Init()); | 223 EXPECT_TRUE(decoded_frame_writer_->Init()); |
221 } | 224 } |
222 } | 225 } |
223 | 226 |
224 packet_manipulator_.reset(new PacketManipulatorImpl( | 227 packet_manipulator_.reset(new PacketManipulatorImpl( |
225 &packet_reader_, config_.networking_config, config_.verbose)); | 228 &packet_reader_, config_.networking_config, config_.verbose)); |
226 processor_ = rtc::MakeUnique<VideoProcessor>( | 229 |
227 encoder_, decoder_, analysis_frame_reader_.get(), | 230 config_.codec_settings.minBitrate = 0; |
228 analysis_frame_writer_.get(), packet_manipulator_.get(), config_, | 231 config_.codec_settings.startBitrate = initial_bitrate_kbps; |
229 &stats_, encoded_frame_writer_.get(), decoded_frame_writer_.get()); | 232 config_.codec_settings.maxFramerate = initial_framerate_fps; |
230 processor_->Init(); | 233 |
234 rtc::Event sync_event(false, false); | |
235 task_queue->PostTask([this, &sync_event]() { | |
236 processor_ = rtc::MakeUnique<VideoProcessor>( | |
237 encoder_, decoder_, analysis_frame_reader_.get(), | |
238 analysis_frame_writer_.get(), packet_manipulator_.get(), config_, | |
239 &stats_, encoded_frame_writer_.get(), decoded_frame_writer_.get()); | |
240 processor_->Init(); | |
241 sync_event.Set(); | |
242 }); | |
243 sync_event.Wait(rtc::Event::kForever); | |
244 } | |
245 | |
246 void ReleaseAndCloseObjects(rtc::TaskQueue* task_queue) { | |
247 rtc::Event sync_event(false, false); | |
248 task_queue->PostTask([this, &sync_event]() { | |
249 processor_->Release(); | |
250 sync_event.Set(); | |
251 }); | |
252 sync_event.Wait(rtc::Event::kForever); | |
253 | |
254 // The VideoProcessor must be ::Release()'d before we destroy the codecs. | |
255 DestroyEncoderAndDecoder(); | |
256 | |
257 // Close the analysis files before we use them for SSIM/PSNR calculations. | |
258 analysis_frame_reader_->Close(); | |
259 analysis_frame_writer_->Close(); | |
260 | |
261 // Close visualization files. | |
262 if (encoded_frame_writer_) { | |
263 EXPECT_TRUE(encoded_frame_writer_->Close()); | |
264 } | |
265 if (decoded_frame_writer_) { | |
266 decoded_frame_writer_->Close(); | |
267 } | |
231 } | 268 } |
232 | 269 |
233 // Reset quantities after each encoder update, update the target per-frame | 270 // Reset quantities after each encoder update, update the target per-frame |
234 // bandwidth. | 271 // bandwidth. |
235 void ResetRateControlMetrics(int num_frames_to_hit_target) { | 272 void ResetRateControlMetrics(int num_frames_to_hit_target) { |
236 const int num_temporal_layers = | 273 const int num_temporal_layers = |
237 NumberOfTemporalLayers(config_.codec_settings); | 274 NumberOfTemporalLayers(config_.codec_settings); |
238 for (int i = 0; i < num_temporal_layers; i++) { | 275 for (int i = 0; i < num_temporal_layers; i++) { |
239 num_frames_per_update_[i] = 0; | 276 num_frames_per_update_[i] = 0; |
240 sum_frame_size_mismatch_[i] = 0.0f; | 277 sum_frame_size_mismatch_[i] = 0.0f; |
(...skipping 18 matching lines...) Expand all Loading... | |
259 num_frames_to_hit_target_ = num_frames_to_hit_target; | 296 num_frames_to_hit_target_ = num_frames_to_hit_target; |
260 encoding_rate_within_target_ = false; | 297 encoding_rate_within_target_ = false; |
261 sum_key_frame_size_mismatch_ = 0.0; | 298 sum_key_frame_size_mismatch_ = 0.0; |
262 num_key_frames_ = 0; | 299 num_key_frames_ = 0; |
263 } | 300 } |
264 | 301 |
265 // For every encoded frame, update the rate control metrics. | 302 // For every encoded frame, update the rate control metrics. |
266 void UpdateRateControlMetrics(int frame_number) { | 303 void UpdateRateControlMetrics(int frame_number) { |
267 RTC_CHECK_GE(frame_number, 0); | 304 RTC_CHECK_GE(frame_number, 0); |
268 | 305 |
306 const int tl_idx = TemporalLayerIndexForFrame(frame_number); | |
307 ++num_frames_per_update_[tl_idx]; | |
308 ++num_frames_total_; | |
309 | |
269 FrameType frame_type = stats_.stats_[frame_number].frame_type; | 310 FrameType frame_type = stats_.stats_[frame_number].frame_type; |
270 float encoded_size_kbits = | 311 float encoded_size_kbits = |
271 stats_.stats_[frame_number].encoded_frame_length_in_bytes * 8.0f / | 312 stats_.stats_[frame_number].encoded_frame_length_in_bytes * 8.0f / |
272 1000.0f; | 313 1000.0f; |
273 const int tl_idx = TemporalLayerIndexForFrame(frame_number); | |
274 | 314 |
275 // Update layer data. | 315 // Update layer data. |
276 // Update rate mismatch relative to per-frame bandwidth for delta frames. | 316 // Update rate mismatch relative to per-frame bandwidth for delta frames. |
277 if (frame_type == kVideoFrameDelta) { | 317 if (frame_type == kVideoFrameDelta) { |
278 // TODO(marpan): Should we count dropped (zero size) frames in mismatch? | 318 // TODO(marpan): Should we count dropped (zero size) frames in mismatch? |
279 sum_frame_size_mismatch_[tl_idx] += | 319 sum_frame_size_mismatch_[tl_idx] += |
280 fabs(encoded_size_kbits - per_frame_bandwidth_[tl_idx]) / | 320 fabs(encoded_size_kbits - per_frame_bandwidth_[tl_idx]) / |
281 per_frame_bandwidth_[tl_idx]; | 321 per_frame_bandwidth_[tl_idx]; |
282 } else { | 322 } else { |
283 float target_size = (frame_number == 0) ? target_size_key_frame_initial_ | 323 float target_size = (frame_number == 0) ? target_size_key_frame_initial_ |
(...skipping 17 matching lines...) Expand all Loading... | |
301 if (perc_encoding_rate_mismatch_ < kPercTargetvsActualMismatch && | 341 if (perc_encoding_rate_mismatch_ < kPercTargetvsActualMismatch && |
302 !encoding_rate_within_target_) { | 342 !encoding_rate_within_target_) { |
303 num_frames_to_hit_target_ = num_frames_total_; | 343 num_frames_to_hit_target_ = num_frames_total_; |
304 encoding_rate_within_target_ = true; | 344 encoding_rate_within_target_ = true; |
305 } | 345 } |
306 } | 346 } |
307 | 347 |
308 // Verify expected behavior of rate control and print out data. | 348 // Verify expected behavior of rate control and print out data. |
309 void PrintAndMaybeVerifyRateControlMetrics( | 349 void PrintAndMaybeVerifyRateControlMetrics( |
310 int rate_update_index, | 350 int rate_update_index, |
311 const std::vector<RateControlThresholds>* rc_thresholds) { | 351 const std::vector<RateControlThresholds>* rc_thresholds, |
312 int num_dropped_frames = processor_->NumberDroppedFrames(); | 352 const std::vector<int>& num_dropped_frames, |
313 int num_resize_actions = processor_->NumberSpatialResizes(); | 353 const std::vector<int>& num_resize_actions) { |
314 printf( | 354 printf( |
315 "Rate update #%d:\n" | 355 "Rate update #%d:\n" |
316 " Target bitrate : %d\n" | 356 " Target bitrate : %d\n" |
317 " Encoded bitrate : %f\n" | 357 " Encoded bitrate : %f\n" |
318 " Frame rate : %d\n", | 358 " Frame rate : %d\n", |
319 rate_update_index, bitrate_kbps_, encoding_bitrate_total_, framerate_); | 359 rate_update_index, bitrate_kbps_, encoding_bitrate_total_, framerate_); |
320 printf( | 360 printf( |
321 " # processed frames : %d\n" | 361 " # processed frames : %d\n" |
322 " # frames to convergence: %d\n" | 362 " # frames to convergence: %d\n" |
323 " # dropped frames : %d\n" | 363 " # dropped frames : %d\n" |
324 " # spatial resizes : %d\n", | 364 " # spatial resizes : %d\n", |
325 num_frames_total_, num_frames_to_hit_target_, num_dropped_frames, | 365 num_frames_total_, num_frames_to_hit_target_, |
326 num_resize_actions); | 366 num_dropped_frames[rate_update_index], |
367 num_resize_actions[rate_update_index]); | |
327 | 368 |
328 const RateControlThresholds* rc_threshold = nullptr; | 369 const RateControlThresholds* rc_threshold = nullptr; |
329 if (rc_thresholds) { | 370 if (rc_thresholds) { |
330 rc_threshold = &(*rc_thresholds)[rate_update_index]; | 371 rc_threshold = &(*rc_thresholds)[rate_update_index]; |
331 | 372 |
332 EXPECT_LE(perc_encoding_rate_mismatch_, | 373 EXPECT_LE(perc_encoding_rate_mismatch_, |
333 rc_threshold->max_encoding_rate_mismatch); | 374 rc_threshold->max_encoding_rate_mismatch); |
334 } | 375 } |
335 if (num_key_frames_ > 0) { | 376 if (num_key_frames_ > 0) { |
336 int perc_key_frame_size_mismatch = | 377 int perc_key_frame_size_mismatch = |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
369 EXPECT_LE(perc_frame_size_mismatch, | 410 EXPECT_LE(perc_frame_size_mismatch, |
370 rc_threshold->max_delta_frame_size_mismatch); | 411 rc_threshold->max_delta_frame_size_mismatch); |
371 EXPECT_LE(perc_encoding_rate_mismatch, | 412 EXPECT_LE(perc_encoding_rate_mismatch, |
372 rc_threshold->max_encoding_rate_mismatch); | 413 rc_threshold->max_encoding_rate_mismatch); |
373 } | 414 } |
374 } | 415 } |
375 printf("\n"); | 416 printf("\n"); |
376 | 417 |
377 if (rc_threshold) { | 418 if (rc_threshold) { |
378 EXPECT_LE(num_frames_to_hit_target_, rc_threshold->max_time_hit_target); | 419 EXPECT_LE(num_frames_to_hit_target_, rc_threshold->max_time_hit_target); |
379 EXPECT_LE(num_dropped_frames, rc_threshold->max_num_dropped_frames); | 420 EXPECT_LE(num_dropped_frames[rate_update_index], |
380 EXPECT_EQ(rc_threshold->num_spatial_resizes, num_resize_actions); | 421 rc_threshold->max_num_dropped_frames); |
422 EXPECT_EQ(rc_threshold->num_spatial_resizes, | |
423 num_resize_actions[rate_update_index]); | |
381 EXPECT_EQ(rc_threshold->num_key_frames, num_key_frames_); | 424 EXPECT_EQ(rc_threshold->num_key_frames, num_key_frames_); |
382 } | 425 } |
383 } | 426 } |
384 | 427 |
385 static void VerifyQuality(const QualityMetricsResult& psnr_result, | 428 static void VerifyQuality(const QualityMetricsResult& psnr_result, |
386 const QualityMetricsResult& ssim_result, | 429 const QualityMetricsResult& ssim_result, |
387 const QualityThresholds& quality_thresholds) { | 430 const QualityThresholds& quality_thresholds) { |
388 EXPECT_GT(psnr_result.average, quality_thresholds.min_avg_psnr); | 431 EXPECT_GT(psnr_result.average, quality_thresholds.min_avg_psnr); |
389 EXPECT_GT(psnr_result.min, quality_thresholds.min_min_psnr); | 432 EXPECT_GT(psnr_result.min, quality_thresholds.min_min_psnr); |
390 EXPECT_GT(ssim_result.average, quality_thresholds.min_avg_ssim); | 433 EXPECT_GT(ssim_result.average, quality_thresholds.min_avg_ssim); |
391 EXPECT_GT(ssim_result.min, quality_thresholds.min_min_ssim); | 434 EXPECT_GT(ssim_result.min, quality_thresholds.min_min_ssim); |
392 } | 435 } |
393 | 436 |
394 void VerifyQpParser(int frame_number) { | |
395 if (!config_.hw_codec && | |
396 (config_.codec_settings.codecType == kVideoCodecVP8 || | |
397 config_.codec_settings.codecType == kVideoCodecVP9)) { | |
398 EXPECT_EQ(processor_->GetQpFromEncoder(frame_number), | |
399 processor_->GetQpFromBitstream(frame_number)); | |
400 } | |
401 } | |
402 | |
403 static int NumberOfTemporalLayers(const VideoCodec& codec_settings) { | 437 static int NumberOfTemporalLayers(const VideoCodec& codec_settings) { |
404 if (codec_settings.codecType == kVideoCodecVP8) { | 438 if (codec_settings.codecType == kVideoCodecVP8) { |
405 return codec_settings.VP8().numberOfTemporalLayers; | 439 return codec_settings.VP8().numberOfTemporalLayers; |
406 } else if (codec_settings.codecType == kVideoCodecVP9) { | 440 } else if (codec_settings.codecType == kVideoCodecVP9) { |
407 return codec_settings.VP9().numberOfTemporalLayers; | 441 return codec_settings.VP9().numberOfTemporalLayers; |
408 } else { | 442 } else { |
409 return 1; | 443 return 1; |
410 } | 444 } |
411 } | 445 } |
412 | 446 |
(...skipping 23 matching lines...) Expand all Loading... | |
436 tl_idx = 2; | 470 tl_idx = 2; |
437 } | 471 } |
438 break; | 472 break; |
439 default: | 473 default: |
440 RTC_NOTREACHED(); | 474 RTC_NOTREACHED(); |
441 break; | 475 break; |
442 } | 476 } |
443 return tl_idx; | 477 return tl_idx; |
444 } | 478 } |
445 | 479 |
446 // Set the bit rate and frame rate per temporal layer, for up to 3 layers. | 480 void UpdateRates(int rate_update_index, const RateProfile& rate_profile) { |
447 void SetTemporalLayerRates() { | 481 bitrate_kbps_ = rate_profile.target_bit_rate[rate_update_index]; |
482 framerate_ = rate_profile.input_frame_rate[rate_update_index]; | |
483 | |
448 const int num_temporal_layers = | 484 const int num_temporal_layers = |
449 NumberOfTemporalLayers(config_.codec_settings); | 485 NumberOfTemporalLayers(config_.codec_settings); |
450 RTC_DCHECK_LE(num_temporal_layers, kMaxNumTemporalLayers); | 486 RTC_DCHECK_LE(num_temporal_layers, kMaxNumTemporalLayers); |
451 for (int i = 0; i < num_temporal_layers; i++) { | 487 for (int i = 0; i < num_temporal_layers; i++) { |
452 float bit_rate_ratio = kVp8LayerRateAlloction[num_temporal_layers - 1][i]; | 488 float bit_rate_ratio = kVp8LayerRateAlloction[num_temporal_layers - 1][i]; |
453 if (i > 0) { | 489 if (i > 0) { |
454 float bit_rate_delta_ratio = | 490 float bit_rate_delta_ratio = |
455 kVp8LayerRateAlloction[num_temporal_layers - 1][i] - | 491 kVp8LayerRateAlloction[num_temporal_layers - 1][i] - |
456 kVp8LayerRateAlloction[num_temporal_layers - 1][i - 1]; | 492 kVp8LayerRateAlloction[num_temporal_layers - 1][i - 1]; |
457 bitrate_layer_[i] = bitrate_kbps_ * bit_rate_delta_ratio; | 493 bitrate_layer_[i] = bitrate_kbps_ * bit_rate_delta_ratio; |
458 } else { | 494 } else { |
459 bitrate_layer_[i] = bitrate_kbps_ * bit_rate_ratio; | 495 bitrate_layer_[i] = bitrate_kbps_ * bit_rate_ratio; |
460 } | 496 } |
461 framerate_layer_[i] = | 497 framerate_layer_[i] = |
462 framerate_ / static_cast<float>(1 << (num_temporal_layers - 1)); | 498 framerate_ / static_cast<float>(1 << (num_temporal_layers - 1)); |
463 } | 499 } |
464 if (num_temporal_layers == 3) { | 500 if (num_temporal_layers == 3) { |
465 framerate_layer_[2] = framerate_ / 2.0f; | 501 framerate_layer_[2] = framerate_ / 2.0f; |
466 } | 502 } |
467 } | 503 } |
468 | 504 |
469 // Processes all frames in the clip and verifies the result. | 505 // Processes all frames in the clip and verifies the result. |
470 void ProcessFramesAndMaybeVerify( | 506 void ProcessFramesAndMaybeVerify( |
471 const RateProfile& rate_profile, | 507 const RateProfile& rate_profile, |
472 const std::vector<RateControlThresholds>* rc_thresholds, | 508 const std::vector<RateControlThresholds>* rc_thresholds, |
473 const QualityThresholds* quality_thresholds, | 509 const QualityThresholds* quality_thresholds, |
474 const VisualizationParams* visualization_params) { | 510 const VisualizationParams* visualization_params) { |
475 config_.codec_settings.startBitrate = rate_profile.target_bit_rate[0]; | 511 // The Android HW codec needs to be run on a task queue, so we simply always |
476 SetUpObjects(visualization_params, rate_profile.target_bit_rate[0], | 512 // run the test on a task queue. |
477 rate_profile.input_frame_rate[0]); | 513 rtc::TaskQueue task_queue("VidProc TQ"); |
514 rtc::Event sync_event(false, false); | |
515 | |
516 SetUpAndInitObjects(&task_queue, rate_profile.target_bit_rate[0], | |
517 rate_profile.input_frame_rate[0], visualization_params); | |
478 | 518 |
479 // Set initial rates. | 519 // Set initial rates. |
480 bitrate_kbps_ = rate_profile.target_bit_rate[0]; | 520 int rate_update_index = 0; |
481 framerate_ = rate_profile.input_frame_rate[0]; | 521 task_queue.PostTask([this, &rate_profile, rate_update_index] { |
482 SetTemporalLayerRates(); | 522 processor_->SetRates(rate_profile.target_bit_rate[rate_update_index], |
483 // Set the initial target size for key frame. | 523 rate_profile.input_frame_rate[rate_update_index]); |
524 }); | |
525 | |
526 // Process all frames. | |
527 int frame_number = 0; | |
528 const int num_frames = rate_profile.num_frames; | |
529 RTC_DCHECK_GE(num_frames, 1); | |
530 while (frame_number < num_frames) { | |
531 // In order to not overwhelm the OpenMAX buffers in the Android | |
532 // MediaCodec API, we roughly pace the frames here. The downside | |
533 // of this is that the encode run will be done in real-time. | |
534 // TODO(brandtr): Investigate if this is needed on iOS. | |
535 if (config_.hw_codec) { | |
536 SleepMs(rtc::kNumMillisecsPerSec / | |
537 rate_profile.input_frame_rate[rate_update_index]); | |
538 } | |
539 | |
540 task_queue.PostTask( | |
541 [this, frame_number] { processor_->ProcessFrame(frame_number); }); | |
542 ++frame_number; | |
543 | |
544 if (frame_number == | |
545 rate_profile.frame_index_rate_update[rate_update_index + 1]) { | |
546 ++rate_update_index; | |
547 | |
548 task_queue.PostTask([this, &rate_profile, rate_update_index] { | |
549 processor_->SetRates( | |
550 rate_profile.target_bit_rate[rate_update_index], | |
551 rate_profile.input_frame_rate[rate_update_index]); | |
552 }); | |
553 } | |
554 } | |
555 | |
556 // TODO(brandtr): Verify the assumption that HW codecs never | |
557 // drop frames internally. | |
558 if (config_.hw_codec) { | |
559 // Ensure that all the frames have been encoded and decoded. | |
560 int last_decoded_frame_num = -1; | |
561 int wait_count = 0; | |
562 while (last_decoded_frame_num != (num_frames - 1) && wait_count++ < 10) { | |
563 sync_event.Reset(); | |
564 task_queue.PostTask([this, &last_decoded_frame_num, &sync_event]() { | |
565 last_decoded_frame_num = processor_->LastDecodedFrameNumber(); | |
566 sync_event.Set(); | |
567 }); | |
568 sync_event.Wait(rtc::Event::kForever); | |
569 | |
570 SleepMs(1000); | |
571 } | |
572 EXPECT_LT(wait_count, 10) << "Lost frames in the VideoProcessor."; | |
573 } | |
574 | |
575 ReleaseAndCloseObjects(&task_queue); | |
576 | |
577 // Verify QP parsing. | |
578 // TODO(brandtr): This verification is somewhat orthogonal to the rest of | |
579 // this test, which is focused on measuring image quality and rate control | |
580 // quality. We should create a whole separate test that verifies the QP | |
581 // parsing. This could be done by instantiating a VideoProcessor, encoding | |
582 // a number of frames, and then verifying the parsing. | |
583 if (!config_.hw_codec && | |
584 (config_.codec_settings.codecType == kVideoCodecVP8 || | |
585 config_.codec_settings.codecType == kVideoCodecVP9)) { | |
586 for (int frame_number = 0; frame_number < num_frames; ++frame_number) { | |
587 task_queue.PostTask([this, frame_number] { | |
588 EXPECT_EQ(processor_->GetQpFromEncoder(frame_number), | |
589 processor_->GetQpFromBitstream(frame_number)); | |
590 }); | |
591 } | |
592 } | |
593 | |
594 // Calculate and print rate control statistics. | |
595 rate_update_index = 0; | |
596 frame_number = 0; | |
597 UpdateRates(rate_update_index, rate_profile); | |
598 ResetRateControlMetrics( | |
599 rate_profile.frame_index_rate_update[rate_update_index + 1]); | |
484 target_size_key_frame_initial_ = | 600 target_size_key_frame_initial_ = |
485 0.5 * kInitialBufferSize * bitrate_layer_[0]; | 601 0.5 * kInitialBufferSize * bitrate_layer_[0]; |
åsapersson
2017/08/29 13:42:33
maybe move to ResetRateControlMetrics?
brandtr
2017/08/30 11:44:26
Done.
| |
486 processor_->SetRates(bitrate_kbps_, framerate_); | 602 std::vector<int> num_dropped_frames; |
487 | 603 std::vector<int> num_resize_actions; |
488 // Process each frame, up to |num_frames|. | 604 sync_event.Reset(); |
489 int frame_number = 0; | 605 task_queue.PostTask( |
490 int update_index = 0; | 606 [this, &num_dropped_frames, &num_resize_actions, &sync_event]() { |
491 int num_frames = rate_profile.num_frames; | 607 num_dropped_frames = processor_->NumberDroppedFramesPerRateUpdate(); |
492 ResetRateControlMetrics( | 608 num_resize_actions = processor_->NumberSpatialResizesPerRateUpdate(); |
493 rate_profile.frame_index_rate_update[update_index + 1]); | 609 sync_event.Set(); |
494 | 610 }); |
611 sync_event.Wait(rtc::Event::kForever); | |
495 while (frame_number < num_frames) { | 612 while (frame_number < num_frames) { |
496 processor_->ProcessFrame(frame_number); | |
497 VerifyQpParser(frame_number); | |
498 const int tl_idx = TemporalLayerIndexForFrame(frame_number); | |
499 ++num_frames_per_update_[tl_idx]; | |
500 ++num_frames_total_; | |
501 UpdateRateControlMetrics(frame_number); | 613 UpdateRateControlMetrics(frame_number); |
502 | 614 |
503 ++frame_number; | 615 ++frame_number; |
504 | 616 |
505 // If we hit another/next update, verify stats for current state and | |
506 // update layers and codec with new rates. | |
507 if (frame_number == | 617 if (frame_number == |
508 rate_profile.frame_index_rate_update[update_index + 1]) { | 618 rate_profile.frame_index_rate_update[rate_update_index + 1]) { |
509 PrintAndMaybeVerifyRateControlMetrics(update_index, rc_thresholds); | 619 PrintAndMaybeVerifyRateControlMetrics(rate_update_index, rc_thresholds, |
510 | 620 num_dropped_frames, |
511 // Update layer rates and the codec with new rates. | 621 num_resize_actions); |
512 ++update_index; | 622 ++rate_update_index; |
513 bitrate_kbps_ = rate_profile.target_bit_rate[update_index]; | 623 UpdateRates(rate_update_index, rate_profile); |
514 framerate_ = rate_profile.input_frame_rate[update_index]; | |
515 SetTemporalLayerRates(); | |
516 ResetRateControlMetrics( | 624 ResetRateControlMetrics( |
517 rate_profile.frame_index_rate_update[update_index + 1]); | 625 rate_profile.frame_index_rate_update[rate_update_index + 1]); |
åsapersson
2017/08/29 13:42:33
call ResetRateControlMetrics from UpdateRates?
brandtr
2017/08/30 11:44:26
Done: merged the two functions into one.
| |
518 processor_->SetRates(bitrate_kbps_, framerate_); | |
519 } | 626 } |
520 } | 627 } |
628 PrintAndMaybeVerifyRateControlMetrics(rate_update_index, rc_thresholds, | |
629 num_dropped_frames, | |
630 num_resize_actions); | |
521 | 631 |
522 // Verify rate control metrics for all frames since the last rate update. | 632 // Calculate and print other statistics. |
523 PrintAndMaybeVerifyRateControlMetrics(update_index, rc_thresholds); | |
524 EXPECT_EQ(num_frames, frame_number); | |
525 EXPECT_EQ(num_frames, static_cast<int>(stats_.stats_.size())); | 633 EXPECT_EQ(num_frames, static_cast<int>(stats_.stats_.size())); |
634 stats_.PrintSummary(); | |
526 | 635 |
527 // Release encoder and decoder to make sure they have finished processing. | 636 // Calculate and print image quality statistics. |
528 processor_->Release(); | |
529 DestroyEncoderAndDecoder(); | |
530 | |
531 // Close the analysis files before we use them for SSIM/PSNR calculations. | |
532 analysis_frame_reader_->Close(); | |
533 analysis_frame_writer_->Close(); | |
534 | |
535 // Close visualization files. | |
536 if (encoded_frame_writer_) { | |
537 EXPECT_TRUE(encoded_frame_writer_->Close()); | |
538 } | |
539 if (decoded_frame_writer_) { | |
540 decoded_frame_writer_->Close(); | |
541 } | |
542 | |
543 // TODO(marpan): Should compute these quality metrics per SetRates update. | 637 // TODO(marpan): Should compute these quality metrics per SetRates update. |
544 QualityMetricsResult psnr_result, ssim_result; | 638 QualityMetricsResult psnr_result, ssim_result; |
545 EXPECT_EQ(0, I420MetricsFromFiles(config_.input_filename.c_str(), | 639 EXPECT_EQ(0, I420MetricsFromFiles(config_.input_filename.c_str(), |
546 config_.output_filename.c_str(), | 640 config_.output_filename.c_str(), |
547 config_.codec_settings.width, | 641 config_.codec_settings.width, |
548 config_.codec_settings.height, | 642 config_.codec_settings.height, |
549 &psnr_result, &ssim_result)); | 643 &psnr_result, &ssim_result)); |
550 if (quality_thresholds) { | 644 if (quality_thresholds) { |
551 VerifyQuality(psnr_result, ssim_result, *quality_thresholds); | 645 VerifyQuality(psnr_result, ssim_result, *quality_thresholds); |
552 } | 646 } |
553 stats_.PrintSummary(); | |
554 printf("PSNR avg: %f, min: %f\nSSIM avg: %f, min: %f\n", | 647 printf("PSNR avg: %f, min: %f\nSSIM avg: %f, min: %f\n", |
555 psnr_result.average, psnr_result.min, ssim_result.average, | 648 psnr_result.average, psnr_result.min, ssim_result.average, |
556 ssim_result.min); | 649 ssim_result.min); |
557 printf("\n"); | 650 printf("\n"); |
558 | 651 |
559 // Remove analysis file. | 652 // Remove analysis file. |
560 if (remove(config_.output_filename.c_str()) < 0) { | 653 if (remove(config_.output_filename.c_str()) < 0) { |
561 fprintf(stderr, "Failed to remove temporary file!\n"); | 654 fprintf(stderr, "Failed to remove temporary file!\n"); |
562 } | 655 } |
563 } | 656 } |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
697 float target_size_key_frame_initial_; | 790 float target_size_key_frame_initial_; |
698 float target_size_key_frame_; | 791 float target_size_key_frame_; |
699 float sum_key_frame_size_mismatch_; | 792 float sum_key_frame_size_mismatch_; |
700 int num_key_frames_; | 793 int num_key_frames_; |
701 }; | 794 }; |
702 | 795 |
703 } // namespace test | 796 } // namespace test |
704 } // namespace webrtc | 797 } // namespace webrtc |
705 | 798 |
706 #endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_INTEGRATIONTES T_H_ | 799 #endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_INTEGRATIONTES T_H_ |
OLD | NEW |