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 |
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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
166 // TODO(brandtr): Generalize so that we support multiple profiles here. | 168 // TODO(brandtr): Generalize so that we support multiple profiles here. |
167 encoder_ = encoder_factory_->CreateVideoEncoder( | 169 encoder_ = encoder_factory_->CreateVideoEncoder( |
168 cricket::VideoCodec(cricket::kH264CodecName)); | 170 cricket::VideoCodec(cricket::kH264CodecName)); |
169 decoder_ = decoder_factory_->CreateVideoDecoder(kVideoCodecH264); | 171 decoder_ = decoder_factory_->CreateVideoDecoder(kVideoCodecH264); |
170 break; | 172 break; |
171 default: | 173 default: |
172 RTC_NOTREACHED(); | 174 RTC_NOTREACHED(); |
173 break; | 175 break; |
174 } | 176 } |
175 | 177 |
176 RTC_CHECK(encoder_) << "Encoder not successfully created."; | 178 EXPECT_TRUE(encoder_) << "Encoder not successfully created."; |
177 RTC_CHECK(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 RTC_CHECK(analysis_frame_reader_->Init()); | 200 EXPECT_TRUE(analysis_frame_reader_->Init()); |
198 RTC_CHECK(analysis_frame_writer_->Init()); | 201 EXPECT_TRUE(analysis_frame_writer_->Init()); |
199 | 202 |
200 if (visualization_params) { | 203 if (visualization_params) { |
201 const std::string codec_name = | 204 const std::string codec_name = |
202 CodecTypeToPayloadName(config_.codec_settings.codecType) | 205 CodecTypeToPayloadName(config_.codec_settings.codecType) |
203 .value_or("unknown"); | 206 .value_or("unknown"); |
204 const std::string implementation_type = config_.hw_codec ? "hw" : "sw"; | 207 const std::string implementation_type = config_.hw_codec ? "hw" : "sw"; |
205 // clang-format off | 208 // clang-format off |
206 const std::string output_filename_base = | 209 const std::string output_filename_base = |
207 OutputPath() + config_.filename + "-" + | 210 OutputPath() + config_.filename + "-" + |
208 codec_name + "-" + implementation_type + "-" + | 211 codec_name + "-" + implementation_type + "-" + |
209 std::to_string(initial_bitrate_kbps); | 212 std::to_string(initial_bitrate_kbps); |
210 // clang-format on | 213 // clang-format on |
211 if (visualization_params->save_encoded_ivf) { | 214 if (visualization_params->save_encoded_ivf) { |
212 rtc::File post_encode_file = | 215 rtc::File post_encode_file = |
213 rtc::File::Create(output_filename_base + "_encoded.ivf"); | 216 rtc::File::Create(output_filename_base + ".ivf"); |
214 encoded_frame_writer_ = | 217 encoded_frame_writer_ = |
215 IvfFileWriter::Wrap(std::move(post_encode_file), 0); | 218 IvfFileWriter::Wrap(std::move(post_encode_file), 0); |
216 } | 219 } |
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 + "_decoded.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 RTC_CHECK(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; |
242 sum_encoded_frame_size_[i] = 0.0f; | 277 sum_encoded_frame_size_[i] = 0.0f; |
243 encoding_bitrate_[i] = 0.0f; | 278 encoding_bitrate_[i] = 0.0f; |
244 // Update layer per-frame-bandwidth. | 279 // Update layer per-frame-bandwidth. |
245 per_frame_bandwidth_[i] = static_cast<float>(bit_rate_layer_[i]) / | 280 per_frame_bandwidth_[i] = static_cast<float>(bitrate_layer_[i]) / |
246 static_cast<float>(frame_rate_layer_[i]); | 281 static_cast<float>(framerate_layer_[i]); |
247 } | 282 } |
248 // Set maximum size of key frames, following setting in the VP8 wrapper. | 283 // Set maximum size of key frames, following setting in the VP8 wrapper. |
249 float max_key_size = kScaleKeyFrameSize * kOptimalBufferSize * frame_rate_; | 284 float max_key_size = kScaleKeyFrameSize * kOptimalBufferSize * framerate_; |
250 // We don't know exact target size of the key frames (except for first one), | 285 // We don't know exact target size of the key frames (except for first one), |
251 // but the minimum in libvpx is ~|3 * per_frame_bandwidth| and maximum is | 286 // but the minimum in libvpx is ~|3 * per_frame_bandwidth| and maximum is |
252 // set by |max_key_size_ * per_frame_bandwidth|. Take middle point/average | 287 // set by |max_key_size_ * per_frame_bandwidth|. Take middle point/average |
253 // as reference for mismatch. Note key frames always correspond to base | 288 // as reference for mismatch. Note key frames always correspond to base |
254 // layer frame in this test. | 289 // layer frame in this test. |
255 target_size_key_frame_ = 0.5 * (3 + max_key_size) * per_frame_bandwidth_[0]; | 290 target_size_key_frame_ = 0.5 * (3 + max_key_size) * per_frame_bandwidth_[0]; |
256 num_frames_total_ = 0; | 291 num_frames_total_ = 0; |
257 sum_encoded_frame_size_total_ = 0.0f; | 292 sum_encoded_frame_size_total_ = 0.0f; |
258 encoding_bitrate_total_ = 0.0f; | 293 encoding_bitrate_total_ = 0.0f; |
259 perc_encoding_rate_mismatch_ = 0.0f; | 294 perc_encoding_rate_mismatch_ = 0.0f; |
260 num_frames_to_hit_target_ = num_frames_to_hit_target; | 295 num_frames_to_hit_target_ = num_frames_to_hit_target; |
261 encoding_rate_within_target_ = false; | 296 encoding_rate_within_target_ = false; |
262 sum_key_frame_size_mismatch_ = 0.0; | 297 sum_key_frame_size_mismatch_ = 0.0; |
263 num_key_frames_ = 0; | 298 num_key_frames_ = 0; |
264 } | 299 } |
265 | 300 |
266 // For every encoded frame, update the rate control metrics. | 301 // For every encoded frame, update the rate control metrics. |
267 void UpdateRateControlMetrics(int frame_number) { | 302 void UpdateRateControlMetrics(int frame_number) { |
268 RTC_CHECK_GE(frame_number, 0); | 303 RTC_CHECK_GE(frame_number, 0); |
269 int tl_idx = TemporalLayerIndexForFrame(frame_number); | 304 int tl_idx = TemporalLayerIndexForFrame(frame_number); |
270 FrameType frame_type = processor_->EncodedFrameType(frame_number); | 305 FrameType frame_type = stats_.stats_[frame_number].frame_type; |
271 float encoded_size_kbits = | 306 float encoded_size_kbits = |
272 processor_->EncodedFrameSize(frame_number) * 8.0f / 1000.0f; | 307 stats_.stats_[frame_number].encoded_frame_length_in_bytes * 8.0f / |
| 308 1000.0f; |
273 | 309 |
274 // Update layer data. | 310 // Update layer data. |
275 // Update rate mismatch relative to per-frame bandwidth for delta frames. | 311 // Update rate mismatch relative to per-frame bandwidth for delta frames. |
276 if (frame_type == kVideoFrameDelta) { | 312 if (frame_type == kVideoFrameDelta) { |
277 // TODO(marpan): Should we count dropped (zero size) frames in mismatch? | 313 // TODO(marpan): Should we count dropped (zero size) frames in mismatch? |
278 sum_frame_size_mismatch_[tl_idx] += | 314 sum_frame_size_mismatch_[tl_idx] += |
279 fabs(encoded_size_kbits - per_frame_bandwidth_[tl_idx]) / | 315 fabs(encoded_size_kbits - per_frame_bandwidth_[tl_idx]) / |
280 per_frame_bandwidth_[tl_idx]; | 316 per_frame_bandwidth_[tl_idx]; |
281 } else { | 317 } else { |
282 float target_size = (frame_number == 0) ? target_size_key_frame_initial_ | 318 float target_size = (frame_number == 0) ? target_size_key_frame_initial_ |
283 : target_size_key_frame_; | 319 : target_size_key_frame_; |
284 sum_key_frame_size_mismatch_ += | 320 sum_key_frame_size_mismatch_ += |
285 fabs(encoded_size_kbits - target_size) / target_size; | 321 fabs(encoded_size_kbits - target_size) / target_size; |
286 num_key_frames_ += 1; | 322 num_key_frames_ += 1; |
287 } | 323 } |
288 sum_encoded_frame_size_[tl_idx] += encoded_size_kbits; | 324 sum_encoded_frame_size_[tl_idx] += encoded_size_kbits; |
289 // Encoding bit rate per temporal layer: from the start of the update/run | 325 // Encoding bit rate per temporal layer: from the start of the update/run |
290 // to the current frame. | 326 // to the current frame. |
291 encoding_bitrate_[tl_idx] = sum_encoded_frame_size_[tl_idx] * | 327 encoding_bitrate_[tl_idx] = sum_encoded_frame_size_[tl_idx] * |
292 frame_rate_layer_[tl_idx] / | 328 framerate_layer_[tl_idx] / |
293 num_frames_per_update_[tl_idx]; | 329 num_frames_per_update_[tl_idx]; |
294 // Total encoding rate: from the start of the update/run to current frame. | 330 // Total encoding rate: from the start of the update/run to current frame. |
295 sum_encoded_frame_size_total_ += encoded_size_kbits; | 331 sum_encoded_frame_size_total_ += encoded_size_kbits; |
296 encoding_bitrate_total_ = | 332 encoding_bitrate_total_ = |
297 sum_encoded_frame_size_total_ * frame_rate_ / num_frames_total_; | 333 sum_encoded_frame_size_total_ * framerate_ / num_frames_total_; |
298 perc_encoding_rate_mismatch_ = | 334 perc_encoding_rate_mismatch_ = |
299 100 * fabs(encoding_bitrate_total_ - bit_rate_) / bit_rate_; | 335 100 * fabs(encoding_bitrate_total_ - bitrate_kbps_) / bitrate_kbps_; |
300 if (perc_encoding_rate_mismatch_ < kPercTargetvsActualMismatch && | 336 if (perc_encoding_rate_mismatch_ < kPercTargetvsActualMismatch && |
301 !encoding_rate_within_target_) { | 337 !encoding_rate_within_target_) { |
302 num_frames_to_hit_target_ = num_frames_total_; | 338 num_frames_to_hit_target_ = num_frames_total_; |
303 encoding_rate_within_target_ = true; | 339 encoding_rate_within_target_ = true; |
304 } | 340 } |
305 } | 341 } |
306 | 342 |
307 // Verify expected behavior of rate control and print out data. | 343 // Verify expected behavior of rate control and print out data. |
308 void VerifyRateControlMetrics(int update_index, | 344 void PrintAndMaybeVerifyRateControlMetrics( |
309 const RateControlThresholds& rc_expected) { | 345 int rate_update_index, |
310 int num_dropped_frames = processor_->NumberDroppedFrames(); | 346 const std::vector<RateControlThresholds>* rc_thresholds, |
311 int num_resize_actions = processor_->NumberSpatialResizes(); | 347 const std::vector<int>& num_dropped_frames, |
| 348 const std::vector<int>& num_resize_actions) { |
| 349 const RateControlThresholds* rc_threshold = nullptr; |
| 350 if (rc_thresholds) { |
| 351 rc_threshold = &(*rc_thresholds)[rate_update_index]; |
| 352 |
| 353 EXPECT_LE(perc_encoding_rate_mismatch_, |
| 354 rc_threshold->max_encoding_rate_mismatch); |
| 355 } |
| 356 |
312 printf( | 357 printf( |
313 "Rate update #%d:\n" | 358 "Rate update #%d:\n" |
314 " Target bitrate : %d\n" | 359 " Target bitrate : %d\n" |
315 " Encoded bitrate : %f\n" | 360 " Encoded bitrate : %f\n" |
316 " Frame rate : %d\n", | 361 " Frame rate : %d\n", |
317 update_index, bit_rate_, encoding_bitrate_total_, frame_rate_); | 362 rate_update_index, bitrate_kbps_, encoding_bitrate_total_, framerate_); |
318 printf( | 363 printf( |
319 " # processed frames : %d\n" | 364 " # processed frames : %d\n" |
320 " # frames to convergence: %d\n" | 365 " # frames to convergence: %d\n" |
321 " # dropped frames : %d\n" | 366 " # dropped frames : %d\n" |
322 " # spatial resizes : %d\n", | 367 " # spatial resizes : %d\n", |
323 num_frames_total_, num_frames_to_hit_target_, num_dropped_frames, | 368 num_frames_total_, num_frames_to_hit_target_, |
324 num_resize_actions); | 369 num_dropped_frames[rate_update_index], |
325 EXPECT_LE(perc_encoding_rate_mismatch_, | 370 num_resize_actions[rate_update_index]); |
326 rc_expected.max_encoding_rate_mismatch); | 371 |
327 if (num_key_frames_ > 0) { | 372 if (num_key_frames_ > 0) { |
328 int perc_key_frame_size_mismatch = | 373 int perc_key_frame_size_mismatch = |
329 100 * sum_key_frame_size_mismatch_ / num_key_frames_; | 374 100 * sum_key_frame_size_mismatch_ / num_key_frames_; |
330 printf( | 375 printf( |
331 " # key frames : %d\n" | 376 " # key frames : %d\n" |
332 " Key frame rate mismatch: %d\n", | 377 " Key frame rate mismatch: %d\n", |
333 num_key_frames_, perc_key_frame_size_mismatch); | 378 num_key_frames_, perc_key_frame_size_mismatch); |
334 EXPECT_LE(perc_key_frame_size_mismatch, | 379 if (rc_threshold) { |
335 rc_expected.max_key_frame_size_mismatch); | 380 EXPECT_LE(perc_key_frame_size_mismatch, |
| 381 rc_threshold->max_key_frame_size_mismatch); |
| 382 } |
336 } | 383 } |
| 384 |
337 const int num_temporal_layers = | 385 const int num_temporal_layers = |
338 NumberOfTemporalLayers(config_.codec_settings); | 386 NumberOfTemporalLayers(config_.codec_settings); |
339 for (int i = 0; i < num_temporal_layers; i++) { | 387 for (int i = 0; i < num_temporal_layers; i++) { |
340 printf(" Temporal layer #%d:\n", i); | 388 printf(" Temporal layer #%d:\n", i); |
341 int perc_frame_size_mismatch = | 389 int perc_frame_size_mismatch = |
342 100 * sum_frame_size_mismatch_[i] / num_frames_per_update_[i]; | 390 100 * sum_frame_size_mismatch_[i] / num_frames_per_update_[i]; |
343 int perc_encoding_rate_mismatch = | 391 int perc_encoding_rate_mismatch = |
344 100 * fabs(encoding_bitrate_[i] - bit_rate_layer_[i]) / | 392 100 * fabs(encoding_bitrate_[i] - bitrate_layer_[i]) / |
345 bit_rate_layer_[i]; | 393 bitrate_layer_[i]; |
346 printf( | 394 printf( |
347 " Target layer bitrate : %f\n" | 395 " Target layer bitrate : %f\n" |
348 " Layer frame rate : %f\n" | 396 " Layer frame rate : %f\n" |
349 " Layer per frame bandwidth : %f\n" | 397 " Layer per frame bandwidth : %f\n" |
350 " Layer encoding bitrate : %f\n" | 398 " Layer encoding bitrate : %f\n" |
351 " Layer percent frame size mismatch : %d\n" | 399 " Layer percent frame size mismatch : %d\n" |
352 " Layer percent encoding rate mismatch: %d\n" | 400 " Layer percent encoding rate mismatch: %d\n" |
353 " # frame processed per layer : %d\n", | 401 " # frames processed per layer : %d\n", |
354 bit_rate_layer_[i], frame_rate_layer_[i], per_frame_bandwidth_[i], | 402 bitrate_layer_[i], framerate_layer_[i], per_frame_bandwidth_[i], |
355 encoding_bitrate_[i], perc_frame_size_mismatch, | 403 encoding_bitrate_[i], perc_frame_size_mismatch, |
356 perc_encoding_rate_mismatch, num_frames_per_update_[i]); | 404 perc_encoding_rate_mismatch, num_frames_per_update_[i]); |
357 EXPECT_LE(perc_frame_size_mismatch, | 405 if (rc_threshold) { |
358 rc_expected.max_delta_frame_size_mismatch); | 406 EXPECT_LE(perc_frame_size_mismatch, |
359 EXPECT_LE(perc_encoding_rate_mismatch, | 407 rc_threshold->max_delta_frame_size_mismatch); |
360 rc_expected.max_encoding_rate_mismatch); | 408 EXPECT_LE(perc_encoding_rate_mismatch, |
| 409 rc_threshold->max_encoding_rate_mismatch); |
| 410 } |
361 } | 411 } |
362 printf("\n"); | 412 printf("\n"); |
363 EXPECT_LE(num_frames_to_hit_target_, rc_expected.max_time_hit_target); | 413 |
364 EXPECT_LE(num_dropped_frames, rc_expected.max_num_dropped_frames); | 414 if (rc_threshold) { |
365 if (rc_expected.num_spatial_resizes >= 0) { | 415 EXPECT_LE(num_frames_to_hit_target_, rc_threshold->max_time_hit_target); |
366 EXPECT_EQ(rc_expected.num_spatial_resizes, num_resize_actions); | 416 EXPECT_LE(num_dropped_frames[rate_update_index], |
367 } | 417 rc_threshold->max_num_dropped_frames); |
368 if (rc_expected.num_key_frames >= 0) { | 418 EXPECT_EQ(rc_threshold->num_spatial_resizes, |
369 EXPECT_EQ(rc_expected.num_key_frames, num_key_frames_); | 419 num_resize_actions[rate_update_index]); |
| 420 EXPECT_EQ(rc_threshold->num_key_frames, num_key_frames_); |
370 } | 421 } |
371 } | 422 } |
372 | 423 |
373 void VerifyQuality(const QualityMetricsResult& psnr_result, | 424 static void VerifyQuality(const QualityMetricsResult& psnr_result, |
374 const QualityMetricsResult& ssim_result, | 425 const QualityMetricsResult& ssim_result, |
375 const QualityThresholds& quality_thresholds) { | 426 const QualityThresholds& quality_thresholds) { |
376 EXPECT_GT(psnr_result.average, quality_thresholds.min_avg_psnr); | 427 EXPECT_GT(psnr_result.average, quality_thresholds.min_avg_psnr); |
377 EXPECT_GT(psnr_result.min, quality_thresholds.min_min_psnr); | 428 EXPECT_GT(psnr_result.min, quality_thresholds.min_min_psnr); |
378 EXPECT_GT(ssim_result.average, quality_thresholds.min_avg_ssim); | 429 EXPECT_GT(ssim_result.average, quality_thresholds.min_avg_ssim); |
379 EXPECT_GT(ssim_result.min, quality_thresholds.min_min_ssim); | 430 EXPECT_GT(ssim_result.min, quality_thresholds.min_min_ssim); |
380 } | 431 } |
381 | 432 |
382 void VerifyQpParser(int frame_number) { | 433 static int NumberOfTemporalLayers(const VideoCodec& codec_settings) { |
383 if (!config_.hw_codec && | |
384 (config_.codec_settings.codecType == kVideoCodecVP8 || | |
385 config_.codec_settings.codecType == kVideoCodecVP9)) { | |
386 EXPECT_EQ(processor_->GetQpFromEncoder(frame_number), | |
387 processor_->GetQpFromBitstream(frame_number)); | |
388 } | |
389 } | |
390 | |
391 int NumberOfTemporalLayers(const VideoCodec& codec_settings) { | |
392 if (codec_settings.codecType == kVideoCodecVP8) { | 434 if (codec_settings.codecType == kVideoCodecVP8) { |
393 return codec_settings.VP8().numberOfTemporalLayers; | 435 return codec_settings.VP8().numberOfTemporalLayers; |
394 } else if (codec_settings.codecType == kVideoCodecVP9) { | 436 } else if (codec_settings.codecType == kVideoCodecVP9) { |
395 return codec_settings.VP9().numberOfTemporalLayers; | 437 return codec_settings.VP9().numberOfTemporalLayers; |
396 } else { | 438 } else { |
397 return 1; | 439 return 1; |
398 } | 440 } |
399 } | 441 } |
400 | 442 |
401 // Temporal layer index corresponding to frame number, for up to 3 layers. | 443 // Temporal layer index corresponding to frame number, for up to 3 layers. |
(...skipping 22 matching lines...) Expand all Loading... |
424 tl_idx = 2; | 466 tl_idx = 2; |
425 } | 467 } |
426 break; | 468 break; |
427 default: | 469 default: |
428 RTC_NOTREACHED(); | 470 RTC_NOTREACHED(); |
429 break; | 471 break; |
430 } | 472 } |
431 return tl_idx; | 473 return tl_idx; |
432 } | 474 } |
433 | 475 |
434 // Set the bit rate and frame rate per temporal layer, for up to 3 layers. | 476 void UpdateRates(int rate_update_index, const RateProfile& rate_profile) { |
435 void SetTemporalLayerRates() { | 477 bitrate_kbps_ = rate_profile.target_bit_rate[rate_update_index]; |
| 478 framerate_ = rate_profile.input_frame_rate[rate_update_index]; |
| 479 |
436 const int num_temporal_layers = | 480 const int num_temporal_layers = |
437 NumberOfTemporalLayers(config_.codec_settings); | 481 NumberOfTemporalLayers(config_.codec_settings); |
438 RTC_DCHECK_LE(num_temporal_layers, kMaxNumTemporalLayers); | 482 RTC_DCHECK_LE(num_temporal_layers, kMaxNumTemporalLayers); |
439 for (int i = 0; i < num_temporal_layers; i++) { | 483 for (int i = 0; i < num_temporal_layers; i++) { |
440 float bit_rate_ratio = kVp8LayerRateAlloction[num_temporal_layers - 1][i]; | 484 float bit_rate_ratio = kVp8LayerRateAlloction[num_temporal_layers - 1][i]; |
441 if (i > 0) { | 485 if (i > 0) { |
442 float bit_rate_delta_ratio = | 486 float bit_rate_delta_ratio = |
443 kVp8LayerRateAlloction[num_temporal_layers - 1][i] - | 487 kVp8LayerRateAlloction[num_temporal_layers - 1][i] - |
444 kVp8LayerRateAlloction[num_temporal_layers - 1][i - 1]; | 488 kVp8LayerRateAlloction[num_temporal_layers - 1][i - 1]; |
445 bit_rate_layer_[i] = bit_rate_ * bit_rate_delta_ratio; | 489 bitrate_layer_[i] = bitrate_kbps_ * bit_rate_delta_ratio; |
446 } else { | 490 } else { |
447 bit_rate_layer_[i] = bit_rate_ * bit_rate_ratio; | 491 bitrate_layer_[i] = bitrate_kbps_ * bit_rate_ratio; |
448 } | 492 } |
449 frame_rate_layer_[i] = | 493 framerate_layer_[i] = |
450 frame_rate_ / static_cast<float>(1 << (num_temporal_layers - 1)); | 494 framerate_ / static_cast<float>(1 << (num_temporal_layers - 1)); |
451 } | 495 } |
452 if (num_temporal_layers == 3) { | 496 if (num_temporal_layers == 3) { |
453 frame_rate_layer_[2] = frame_rate_ / 2.0f; | 497 framerate_layer_[2] = framerate_ / 2.0f; |
454 } | 498 } |
455 } | 499 } |
456 | 500 |
457 // Processes all frames in the clip and verifies the result. | 501 // Processes all frames in the clip and verifies the result. |
458 // TODO(brandtr): Change the second last argument to be a | 502 void ProcessFramesAndMaybeVerify( |
459 // const std::vector<RateControlThresholds>&, so we can ensure that the user | 503 const RateProfile& rate_profile, |
460 // does not expect us to do mid-clip rate updates when we are not able to, | 504 const std::vector<RateControlThresholds>* rc_thresholds, |
461 // e.g., when we are operating in batch mode. | 505 const QualityThresholds* quality_thresholds, |
462 void ProcessFramesAndVerify(const QualityThresholds& quality_thresholds, | 506 const VisualizationParams* visualization_params) { |
463 const RateProfile& rate_profile, | 507 // The Android HW codec needs to be run on a task queue, so we simply always |
464 RateControlThresholds* rc_thresholds, | 508 // run the test on a task queue. |
465 const VisualizationParams* visualization_params) { | 509 rtc::TaskQueue task_queue("VidProc TQ"); |
466 config_.codec_settings.startBitrate = rate_profile.target_bit_rate[0]; | 510 |
467 SetUpObjects(visualization_params, rate_profile.target_bit_rate[0], | 511 SetUpAndInitObjects(&task_queue, rate_profile.target_bit_rate[0], |
468 rate_profile.input_frame_rate[0]); | 512 rate_profile.input_frame_rate[0], visualization_params); |
469 | 513 |
470 // Set initial rates. | 514 // Set initial rates. |
471 bit_rate_ = rate_profile.target_bit_rate[0]; | 515 int rate_update_index = 0; |
472 frame_rate_ = rate_profile.input_frame_rate[0]; | 516 task_queue.PostTask([this, &rate_profile, rate_update_index] { |
473 SetTemporalLayerRates(); | 517 processor_->SetRates(rate_profile.target_bit_rate[rate_update_index], |
474 // Set the initial target size for key frame. | 518 rate_profile.input_frame_rate[rate_update_index]); |
475 target_size_key_frame_initial_ = | 519 }); |
476 0.5 * kInitialBufferSize * bit_rate_layer_[0]; | |
477 processor_->SetRates(bit_rate_, frame_rate_); | |
478 | 520 |
479 // Process each frame, up to |num_frames|. | 521 // Process all frames. |
480 int frame_number = 0; | 522 int frame_number = 0; |
481 int update_index = 0; | 523 const int num_frames = rate_profile.num_frames; |
482 int num_frames = rate_profile.num_frames; | 524 while (frame_number < num_frames) { |
483 ResetRateControlMetrics( | 525 // In order to not overwhelm the OpenMAX buffers in the Android |
484 rate_profile.frame_index_rate_update[update_index + 1]); | 526 // MediaCodec API, we roughly pace the frames here. The downside |
485 | 527 // of this is that the encode run will be done in real-time. |
486 if (config_.batch_mode) { | 528 // TODO(brandtr): Investigate if this is needed on iOS. |
487 // In batch mode, we calculate the metrics for all frames after all frames | 529 if (config_.hw_codec) { |
488 // have been sent for encoding. | 530 SleepMs(rtc::kNumMillisecsPerSec / |
489 | 531 rate_profile.input_frame_rate[rate_update_index]); |
490 // TODO(brandtr): Refactor "frame number accounting" so we don't have to | |
491 // call ProcessFrame num_frames+1 times here. | |
492 for (frame_number = 0; frame_number <= num_frames; ++frame_number) { | |
493 EXPECT_TRUE(processor_->ProcessFrame(frame_number)); | |
494 } | 532 } |
495 | 533 |
496 for (frame_number = 0; frame_number < num_frames; ++frame_number) { | 534 task_queue.PostTask( |
497 const int tl_idx = TemporalLayerIndexForFrame(frame_number); | 535 [this, frame_number] { processor_->ProcessFrame(frame_number); }); |
498 ++num_frames_per_update_[tl_idx]; | 536 ++frame_number; |
499 ++num_frames_total_; | 537 |
500 UpdateRateControlMetrics(frame_number); | 538 if (frame_number == |
| 539 rate_profile.frame_index_rate_update[rate_update_index + 1]) { |
| 540 ++rate_update_index; |
| 541 |
| 542 task_queue.PostTask([this, &rate_profile, rate_update_index] { |
| 543 processor_->SetRates( |
| 544 rate_profile.target_bit_rate[rate_update_index], |
| 545 rate_profile.input_frame_rate[rate_update_index]); |
| 546 }); |
501 } | 547 } |
502 } else { | |
503 // In online mode, we calculate the metrics for a given frame right after | |
504 // it has been sent for encoding. | |
505 | |
506 if (config_.hw_codec) { | |
507 LOG(LS_WARNING) << "HW codecs should mostly be run in batch mode, " | |
508 "since they may be pipelining."; | |
509 } | |
510 | |
511 while (frame_number < num_frames) { | |
512 EXPECT_TRUE(processor_->ProcessFrame(frame_number)); | |
513 VerifyQpParser(frame_number); | |
514 const int tl_idx = TemporalLayerIndexForFrame(frame_number); | |
515 ++num_frames_per_update_[tl_idx]; | |
516 ++num_frames_total_; | |
517 UpdateRateControlMetrics(frame_number); | |
518 | |
519 ++frame_number; | |
520 | |
521 // If we hit another/next update, verify stats for current state and | |
522 // update layers and codec with new rates. | |
523 if (frame_number == | |
524 rate_profile.frame_index_rate_update[update_index + 1]) { | |
525 VerifyRateControlMetrics(update_index, rc_thresholds[update_index]); | |
526 | |
527 // Update layer rates and the codec with new rates. | |
528 ++update_index; | |
529 bit_rate_ = rate_profile.target_bit_rate[update_index]; | |
530 frame_rate_ = rate_profile.input_frame_rate[update_index]; | |
531 SetTemporalLayerRates(); | |
532 ResetRateControlMetrics( | |
533 rate_profile.frame_index_rate_update[update_index + 1]); | |
534 processor_->SetRates(bit_rate_, frame_rate_); | |
535 } | |
536 } | |
537 // TODO(brandtr): Refactor "frame number accounting" so we don't have to | |
538 // call ProcessFrame one extra time here. | |
539 EXPECT_TRUE(processor_->ProcessFrame(frame_number)); | |
540 } | 548 } |
541 | 549 |
542 // Verify rate control metrics for all frames (if in batch mode), or for all | 550 // TODO(brandtr): Verify the assumption that HW codecs never |
543 // frames since the last rate update (if not in batch mode). | 551 // drop frames internally. |
544 VerifyRateControlMetrics(update_index, rc_thresholds[update_index]); | 552 if (config_.hw_codec) { |
545 EXPECT_EQ(num_frames, frame_number); | 553 // Ensure that all the frames have been encoded and decoded. |
546 EXPECT_EQ(num_frames + 1, static_cast<int>(stats_.stats_.size())); | 554 rtc::Event sync_event(false, false); |
| 555 int num_frames_decoded = -1; |
| 556 int wait_count = 0; |
| 557 while (num_frames_decoded < num_frames && wait_count++ < 10) { |
| 558 sync_event.Reset(); |
| 559 task_queue.PostTask([this, &num_frames_decoded, &sync_event]() { |
| 560 num_frames_decoded = processor_->NumFramesDecoded(); |
| 561 sync_event.Set(); |
| 562 }); |
| 563 sync_event.Wait(rtc::Event::kForever); |
547 | 564 |
548 // Release encoder and decoder to make sure they have finished processing. | 565 SleepMs(1000); |
549 processor_->Release(); | 566 } |
550 DestroyEncoderAndDecoder(); | 567 EXPECT_LT(wait_count, 10) << "Lost frames in the VideoProcessor."; |
551 | |
552 // Close the analysis files before we use them for SSIM/PSNR calculations. | |
553 analysis_frame_reader_->Close(); | |
554 analysis_frame_writer_->Close(); | |
555 | |
556 // Close visualization files. | |
557 if (encoded_frame_writer_) { | |
558 EXPECT_TRUE(encoded_frame_writer_->Close()); | |
559 } | |
560 if (decoded_frame_writer_) { | |
561 decoded_frame_writer_->Close(); | |
562 } | 568 } |
563 | 569 |
| 570 ReleaseAndCloseObjects(&task_queue); |
| 571 |
| 572 // Verify QP parsing. |
| 573 if (!config_.hw_codec && |
| 574 (config_.codec_settings.codecType == kVideoCodecVP8 || |
| 575 config_.codec_settings.codecType == kVideoCodecVP9)) { |
| 576 for (int frame_number = 0; frame_number < num_frames; ++frame_number) { |
| 577 task_queue.PostTask([this, frame_number] { |
| 578 EXPECT_EQ(processor_->GetQpFromEncoder(frame_number), |
| 579 processor_->GetQpFromBitstream(frame_number)); |
| 580 }); |
| 581 } |
| 582 } |
| 583 |
| 584 // Calculate and print rate control statistics. |
| 585 rate_update_index = 0; |
| 586 frame_number = 0; |
| 587 UpdateRates(rate_update_index, rate_profile); |
| 588 ResetRateControlMetrics( |
| 589 rate_profile.frame_index_rate_update[rate_update_index + 1]); |
| 590 target_size_key_frame_initial_ = |
| 591 0.5 * kInitialBufferSize * bitrate_layer_[0]; |
| 592 std::vector<int> num_dropped_frames; |
| 593 std::vector<int> num_resize_actions; |
| 594 rtc::Event sync_event(false, false); |
| 595 task_queue.PostTask( |
| 596 [this, &num_dropped_frames, &num_resize_actions, &sync_event]() { |
| 597 num_dropped_frames = processor_->NumberDroppedFramesPerRateUpdate(); |
| 598 num_resize_actions = processor_->NumberSpatialResizesPerRateUpdate(); |
| 599 sync_event.Set(); |
| 600 }); |
| 601 sync_event.Wait(rtc::Event::kForever); |
| 602 while (frame_number < num_frames) { |
| 603 const int tl_idx = TemporalLayerIndexForFrame(frame_number); |
| 604 ++num_frames_per_update_[tl_idx]; |
| 605 ++num_frames_total_; |
| 606 UpdateRateControlMetrics(frame_number); |
| 607 |
| 608 ++frame_number; |
| 609 |
| 610 if (frame_number == |
| 611 rate_profile.frame_index_rate_update[rate_update_index + 1]) { |
| 612 PrintAndMaybeVerifyRateControlMetrics(rate_update_index, rc_thresholds, |
| 613 num_dropped_frames, |
| 614 num_resize_actions); |
| 615 ++rate_update_index; |
| 616 UpdateRates(rate_update_index, rate_profile); |
| 617 ResetRateControlMetrics( |
| 618 rate_profile.frame_index_rate_update[rate_update_index + 1]); |
| 619 } |
| 620 } |
| 621 PrintAndMaybeVerifyRateControlMetrics(rate_update_index, rc_thresholds, |
| 622 num_dropped_frames, |
| 623 num_resize_actions); |
| 624 |
| 625 // Calculate and print other statistics. |
| 626 EXPECT_EQ(num_frames, static_cast<int>(stats_.stats_.size())); |
| 627 stats_.PrintSummary(); |
| 628 |
| 629 // Calculate and print image quality statistics. |
564 // TODO(marpan): Should compute these quality metrics per SetRates update. | 630 // TODO(marpan): Should compute these quality metrics per SetRates update. |
565 QualityMetricsResult psnr_result, ssim_result; | 631 QualityMetricsResult psnr_result, ssim_result; |
566 EXPECT_EQ(0, I420MetricsFromFiles(config_.input_filename.c_str(), | 632 EXPECT_EQ(0, I420MetricsFromFiles(config_.input_filename.c_str(), |
567 config_.output_filename.c_str(), | 633 config_.output_filename.c_str(), |
568 config_.codec_settings.width, | 634 config_.codec_settings.width, |
569 config_.codec_settings.height, | 635 config_.codec_settings.height, |
570 &psnr_result, &ssim_result)); | 636 &psnr_result, &ssim_result)); |
571 VerifyQuality(psnr_result, ssim_result, quality_thresholds); | 637 if (quality_thresholds) { |
572 stats_.PrintSummary(); | 638 VerifyQuality(psnr_result, ssim_result, *quality_thresholds); |
| 639 } |
573 printf("PSNR avg: %f, min: %f\nSSIM avg: %f, min: %f\n", | 640 printf("PSNR avg: %f, min: %f\nSSIM avg: %f, min: %f\n", |
574 psnr_result.average, psnr_result.min, ssim_result.average, | 641 psnr_result.average, psnr_result.min, ssim_result.average, |
575 ssim_result.min); | 642 ssim_result.min); |
576 printf("\n"); | 643 printf("\n"); |
577 | 644 |
578 // Remove analysis file. | 645 // Remove analysis file. |
579 if (remove(config_.output_filename.c_str()) < 0) { | 646 if (remove(config_.output_filename.c_str()) < 0) { |
580 fprintf(stderr, "Failed to remove temporary file!\n"); | 647 fprintf(stderr, "Failed to remove temporary file!\n"); |
581 } | 648 } |
582 } | 649 } |
583 | 650 |
584 static void SetTestConfig(TestConfig* config, | 651 static void SetTestConfig(TestConfig* config, |
585 bool hw_codec, | 652 bool hw_codec, |
586 bool use_single_core, | 653 bool use_single_core, |
587 float packet_loss_probability, | 654 float packet_loss_probability, |
588 std::string filename, | 655 std::string filename, |
589 bool verbose_logging, | 656 bool verbose_logging) { |
590 bool batch_mode) { | |
591 config->filename = filename; | 657 config->filename = filename; |
592 config->input_filename = ResourcePath(filename, "yuv"); | 658 config->input_filename = ResourcePath(filename, "yuv"); |
593 // Generate an output filename in a safe way. | 659 // Generate an output filename in a safe way. |
594 config->output_filename = | 660 config->output_filename = |
595 TempFilename(OutputPath(), "videoprocessor_integrationtest"); | 661 TempFilename(OutputPath(), "videoprocessor_integrationtest"); |
596 config->networking_config.packet_loss_probability = packet_loss_probability; | 662 config->networking_config.packet_loss_probability = packet_loss_probability; |
597 config->use_single_core = use_single_core; | 663 config->use_single_core = use_single_core; |
598 config->verbose = verbose_logging; | 664 config->verbose = verbose_logging; |
599 config->hw_codec = hw_codec; | 665 config->hw_codec = hw_codec; |
600 config->batch_mode = batch_mode; | |
601 } | 666 } |
602 | 667 |
603 static void SetCodecSettings(TestConfig* config, | 668 static void SetCodecSettings(TestConfig* config, |
604 VideoCodecType codec_type, | 669 VideoCodecType codec_type, |
605 int num_temporal_layers, | 670 int num_temporal_layers, |
606 bool error_concealment_on, | 671 bool error_concealment_on, |
607 bool denoising_on, | 672 bool denoising_on, |
608 bool frame_dropper_on, | 673 bool frame_dropper_on, |
609 bool spatial_resize_on, | 674 bool spatial_resize_on, |
610 bool resilience_on, | 675 bool resilience_on, |
(...skipping 30 matching lines...) Expand all Loading... |
641 default: | 706 default: |
642 RTC_NOTREACHED(); | 707 RTC_NOTREACHED(); |
643 break; | 708 break; |
644 } | 709 } |
645 | 710 |
646 config->frame_length_in_bytes = | 711 config->frame_length_in_bytes = |
647 CalcBufferSize(VideoType::kI420, width, height); | 712 CalcBufferSize(VideoType::kI420, width, height); |
648 } | 713 } |
649 | 714 |
650 static void SetRateProfile(RateProfile* rate_profile, | 715 static void SetRateProfile(RateProfile* rate_profile, |
651 int update_index, | 716 int rate_update_index, |
652 int bit_rate, | 717 int bit_rate_kbps, |
653 int frame_rate, | 718 int frame_rate_fps, |
654 int frame_index_rate_update) { | 719 int frame_index_rate_update) { |
655 rate_profile->target_bit_rate[update_index] = bit_rate; | 720 rate_profile->target_bit_rate[rate_update_index] = bit_rate_kbps; |
656 rate_profile->input_frame_rate[update_index] = frame_rate; | 721 rate_profile->input_frame_rate[rate_update_index] = frame_rate_fps; |
657 rate_profile->frame_index_rate_update[update_index] = | 722 rate_profile->frame_index_rate_update[rate_update_index] = |
658 frame_index_rate_update; | 723 frame_index_rate_update; |
659 } | 724 } |
660 | 725 |
661 static void SetRateControlThresholds(RateControlThresholds* rc_thresholds, | 726 static void AddRateControlThresholds( |
662 int update_index, | 727 int max_num_dropped_frames, |
663 int max_num_dropped_frames, | 728 int max_key_frame_size_mismatch, |
664 int max_key_frame_size_mismatch, | 729 int max_delta_frame_size_mismatch, |
665 int max_delta_frame_size_mismatch, | 730 int max_encoding_rate_mismatch, |
666 int max_encoding_rate_mismatch, | 731 int max_time_hit_target, |
667 int max_time_hit_target, | 732 int num_spatial_resizes, |
668 int num_spatial_resizes, | 733 int num_key_frames, |
669 int num_key_frames) { | 734 std::vector<RateControlThresholds>* rc_thresholds) { |
670 rc_thresholds[update_index].max_num_dropped_frames = max_num_dropped_frames; | 735 RTC_DCHECK(rc_thresholds); |
671 rc_thresholds[update_index].max_key_frame_size_mismatch = | 736 |
672 max_key_frame_size_mismatch; | 737 rc_thresholds->emplace_back(); |
673 rc_thresholds[update_index].max_delta_frame_size_mismatch = | 738 RateControlThresholds* rc_threshold = &rc_thresholds->back(); |
674 max_delta_frame_size_mismatch; | 739 rc_threshold->max_num_dropped_frames = max_num_dropped_frames; |
675 rc_thresholds[update_index].max_encoding_rate_mismatch = | 740 rc_threshold->max_key_frame_size_mismatch = max_key_frame_size_mismatch; |
676 max_encoding_rate_mismatch; | 741 rc_threshold->max_delta_frame_size_mismatch = max_delta_frame_size_mismatch; |
677 rc_thresholds[update_index].max_time_hit_target = max_time_hit_target; | 742 rc_threshold->max_encoding_rate_mismatch = max_encoding_rate_mismatch; |
678 rc_thresholds[update_index].num_spatial_resizes = num_spatial_resizes; | 743 rc_threshold->max_time_hit_target = max_time_hit_target; |
679 rc_thresholds[update_index].num_key_frames = num_key_frames; | 744 rc_threshold->num_spatial_resizes = num_spatial_resizes; |
| 745 rc_threshold->num_key_frames = num_key_frames; |
680 } | 746 } |
681 | 747 |
682 // Config. | 748 // Config. |
683 TestConfig config_; | 749 TestConfig config_; |
684 | 750 |
685 // Codecs. | 751 // Codecs. |
686 std::unique_ptr<cricket::WebRtcVideoEncoderFactory> encoder_factory_; | 752 std::unique_ptr<cricket::WebRtcVideoEncoderFactory> encoder_factory_; |
687 VideoEncoder* encoder_; | 753 VideoEncoder* encoder_; |
688 std::unique_ptr<cricket::WebRtcVideoDecoderFactory> decoder_factory_; | 754 std::unique_ptr<cricket::WebRtcVideoDecoderFactory> decoder_factory_; |
689 VideoDecoder* decoder_; | 755 VideoDecoder* decoder_; |
690 | 756 |
691 // Helper objects. | 757 // Helper objects. |
692 std::unique_ptr<FrameReader> analysis_frame_reader_; | 758 std::unique_ptr<FrameReader> analysis_frame_reader_; |
693 std::unique_ptr<FrameWriter> analysis_frame_writer_; | 759 std::unique_ptr<FrameWriter> analysis_frame_writer_; |
694 std::unique_ptr<IvfFileWriter> encoded_frame_writer_; | 760 std::unique_ptr<IvfFileWriter> encoded_frame_writer_; |
695 std::unique_ptr<FrameWriter> decoded_frame_writer_; | 761 std::unique_ptr<FrameWriter> decoded_frame_writer_; |
696 PacketReader packet_reader_; | 762 PacketReader packet_reader_; |
697 std::unique_ptr<PacketManipulator> packet_manipulator_; | 763 std::unique_ptr<PacketManipulator> packet_manipulator_; |
698 Stats stats_; | 764 Stats stats_; |
699 std::unique_ptr<VideoProcessor> processor_; | 765 std::unique_ptr<VideoProcessor> processor_; |
700 | 766 |
701 // Quantities defined/updated for every encoder rate update. | 767 // Quantities defined/updated for every encoder rate update. |
702 int num_frames_per_update_[kMaxNumTemporalLayers]; | 768 int num_frames_per_update_[kMaxNumTemporalLayers]; |
703 float sum_frame_size_mismatch_[kMaxNumTemporalLayers]; | 769 float sum_frame_size_mismatch_[kMaxNumTemporalLayers]; |
704 float sum_encoded_frame_size_[kMaxNumTemporalLayers]; | 770 float sum_encoded_frame_size_[kMaxNumTemporalLayers]; |
705 float encoding_bitrate_[kMaxNumTemporalLayers]; | 771 float encoding_bitrate_[kMaxNumTemporalLayers]; |
706 float per_frame_bandwidth_[kMaxNumTemporalLayers]; | 772 float per_frame_bandwidth_[kMaxNumTemporalLayers]; |
707 float bit_rate_layer_[kMaxNumTemporalLayers]; | 773 float bitrate_layer_[kMaxNumTemporalLayers]; |
708 float frame_rate_layer_[kMaxNumTemporalLayers]; | 774 float framerate_layer_[kMaxNumTemporalLayers]; |
709 int num_frames_total_; | 775 int num_frames_total_; |
710 float sum_encoded_frame_size_total_; | 776 float sum_encoded_frame_size_total_; |
711 float encoding_bitrate_total_; | 777 float encoding_bitrate_total_; |
712 float perc_encoding_rate_mismatch_; | 778 float perc_encoding_rate_mismatch_; |
713 int num_frames_to_hit_target_; | 779 int num_frames_to_hit_target_; |
714 bool encoding_rate_within_target_; | 780 bool encoding_rate_within_target_; |
715 int bit_rate_; | 781 int bitrate_kbps_; |
716 int frame_rate_; | 782 int framerate_; |
717 float target_size_key_frame_initial_; | 783 float target_size_key_frame_initial_; |
718 float target_size_key_frame_; | 784 float target_size_key_frame_; |
719 float sum_key_frame_size_mismatch_; | 785 float sum_key_frame_size_mismatch_; |
720 int num_key_frames_; | 786 int num_key_frames_; |
721 }; | 787 }; |
722 | 788 |
723 } // namespace test | 789 } // namespace test |
724 } // namespace webrtc | 790 } // namespace webrtc |
725 | 791 |
726 #endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_INTEGRATIONTES
T_H_ | 792 #endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_INTEGRATIONTES
T_H_ |
OLD | NEW |