OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/modules/video_coding/codecs/test/videoprocessor_integrationtest .h" | 11 #include "webrtc/modules/video_coding/codecs/test/videoprocessor_integrationtest .h" |
12 | 12 |
13 #include <utility> | 13 #include <utility> |
14 | 14 |
15 #if defined(WEBRTC_ANDROID) | 15 #if defined(WEBRTC_ANDROID) |
16 #include "webrtc/modules/video_coding/codecs/test/android_test_initializer.h" | 16 #include "webrtc/modules/video_coding/codecs/test/android_test_initializer.h" |
17 #include "webrtc/sdk/android/src/jni/androidmediadecoder_jni.h" | 17 #include "webrtc/sdk/android/src/jni/androidmediadecoder_jni.h" |
18 #include "webrtc/sdk/android/src/jni/androidmediaencoder_jni.h" | 18 #include "webrtc/sdk/android/src/jni/androidmediaencoder_jni.h" |
19 #elif defined(WEBRTC_IOS) | 19 #elif defined(WEBRTC_IOS) |
20 #include "webrtc/modules/video_coding/codecs/test/objc_codec_h264_test.h" | 20 #include "webrtc/modules/video_coding/codecs/test/objc_codec_h264_test.h" |
21 #endif | 21 #endif |
22 | 22 |
23 #include "webrtc/media/engine/internaldecoderfactory.h" | 23 #include "webrtc/media/engine/internaldecoderfactory.h" |
24 #include "webrtc/media/engine/internalencoderfactory.h" | 24 #include "webrtc/media/engine/internalencoderfactory.h" |
25 #include "webrtc/media/engine/videoencodersoftwarefallbackwrapper.h" | |
25 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h" | 26 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h" |
26 #include "webrtc/modules/video_coding/include/video_codec_interface.h" | 27 #include "webrtc/modules/video_coding/include/video_codec_interface.h" |
27 #include "webrtc/modules/video_coding/include/video_coding.h" | 28 #include "webrtc/modules/video_coding/include/video_coding.h" |
28 #include "webrtc/rtc_base/checks.h" | 29 #include "webrtc/rtc_base/checks.h" |
29 #include "webrtc/rtc_base/event.h" | 30 #include "webrtc/rtc_base/event.h" |
30 #include "webrtc/rtc_base/file.h" | 31 #include "webrtc/rtc_base/file.h" |
31 #include "webrtc/rtc_base/logging.h" | 32 #include "webrtc/rtc_base/logging.h" |
32 #include "webrtc/rtc_base/ptr_util.h" | 33 #include "webrtc/rtc_base/ptr_util.h" |
33 #include "webrtc/system_wrappers/include/sleep.h" | 34 #include "webrtc/system_wrappers/include/sleep.h" |
34 #include "webrtc/test/testsupport/fileutils.h" | 35 #include "webrtc/test/testsupport/fileutils.h" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
82 VideoCodecType codec_type, | 83 VideoCodecType codec_type, |
83 int num_temporal_layers, | 84 int num_temporal_layers, |
84 bool error_concealment_on, | 85 bool error_concealment_on, |
85 bool denoising_on, | 86 bool denoising_on, |
86 bool frame_dropper_on, | 87 bool frame_dropper_on, |
87 bool spatial_resize_on, | 88 bool spatial_resize_on, |
88 bool resilience_on, | 89 bool resilience_on, |
89 int width, | 90 int width, |
90 int height) { | 91 int height) { |
91 webrtc::test::CodecSettings(codec_type, &config->codec_settings); | 92 webrtc::test::CodecSettings(codec_type, &config->codec_settings); |
93 | |
94 // TODO(brandtr): Move the setting of |width| and |height| to the tests, and | |
95 // DCHECK that they are set before initializing the codec instead. | |
92 config->codec_settings.width = width; | 96 config->codec_settings.width = width; |
93 config->codec_settings.height = height; | 97 config->codec_settings.height = height; |
98 | |
94 switch (config->codec_settings.codecType) { | 99 switch (config->codec_settings.codecType) { |
95 case kVideoCodecVP8: | 100 case kVideoCodecVP8: |
96 config->codec_settings.VP8()->resilience = | 101 config->codec_settings.VP8()->resilience = |
97 resilience_on ? kResilientStream : kResilienceOff; | 102 resilience_on ? kResilientStream : kResilienceOff; |
98 config->codec_settings.VP8()->numberOfTemporalLayers = | 103 config->codec_settings.VP8()->numberOfTemporalLayers = |
99 num_temporal_layers; | 104 num_temporal_layers; |
100 config->codec_settings.VP8()->denoisingOn = denoising_on; | 105 config->codec_settings.VP8()->denoisingOn = denoising_on; |
101 config->codec_settings.VP8()->errorConcealmentOn = error_concealment_on; | 106 config->codec_settings.VP8()->errorConcealmentOn = error_concealment_on; |
102 config->codec_settings.VP8()->automaticResizeOn = spatial_resize_on; | 107 config->codec_settings.VP8()->automaticResizeOn = spatial_resize_on; |
103 config->codec_settings.VP8()->frameDroppingOn = frame_dropper_on; | 108 config->codec_settings.VP8()->frameDroppingOn = frame_dropper_on; |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
179 | 184 |
180 // Process all frames. | 185 // Process all frames. |
181 int frame_number = 0; | 186 int frame_number = 0; |
182 const int num_frames = rate_profile.num_frames; | 187 const int num_frames = rate_profile.num_frames; |
183 RTC_DCHECK_GE(num_frames, 1); | 188 RTC_DCHECK_GE(num_frames, 1); |
184 while (frame_number < num_frames) { | 189 while (frame_number < num_frames) { |
185 // In order to not overwhelm the OpenMAX buffers in the Android | 190 // In order to not overwhelm the OpenMAX buffers in the Android |
186 // MediaCodec API, we roughly pace the frames here. The downside | 191 // MediaCodec API, we roughly pace the frames here. The downside |
187 // of this is that the encode run will be done in real-time. | 192 // of this is that the encode run will be done in real-time. |
188 // TODO(brandtr): Investigate if this is needed on iOS. | 193 // TODO(brandtr): Investigate if this is needed on iOS. |
189 if (config_.hw_codec) { | 194 if (config_.hw_encoder || config_.hw_decoder) { |
190 SleepMs(rtc::kNumMillisecsPerSec / | 195 SleepMs(rtc::kNumMillisecsPerSec / |
191 rate_profile.input_frame_rate[rate_update_index]); | 196 rate_profile.input_frame_rate[rate_update_index]); |
192 } | 197 } |
193 | 198 |
194 task_queue.PostTask( | 199 task_queue.PostTask( |
195 [this, frame_number] { processor_->ProcessFrame(frame_number); }); | 200 [this, frame_number] { processor_->ProcessFrame(frame_number); }); |
196 ++frame_number; | 201 ++frame_number; |
197 | 202 |
198 if (frame_number == | 203 if (frame_number == |
199 rate_profile.frame_index_rate_update[rate_update_index + 1]) { | 204 rate_profile.frame_index_rate_update[rate_update_index + 1]) { |
200 ++rate_update_index; | 205 ++rate_update_index; |
201 | 206 |
202 task_queue.PostTask([this, &rate_profile, rate_update_index] { | 207 task_queue.PostTask([this, &rate_profile, rate_update_index] { |
203 processor_->SetRates(rate_profile.target_bit_rate[rate_update_index], | 208 processor_->SetRates(rate_profile.target_bit_rate[rate_update_index], |
204 rate_profile.input_frame_rate[rate_update_index]); | 209 rate_profile.input_frame_rate[rate_update_index]); |
205 }); | 210 }); |
206 } | 211 } |
207 } | 212 } |
208 | 213 |
209 // Give the VideoProcessor pipeline some time to process the last frame, | 214 // Give the VideoProcessor pipeline some time to process the last frame, |
210 // and then release the codecs. | 215 // and then release the codecs. |
211 if (config_.hw_codec) { | 216 if (config_.hw_encoder || config_.hw_decoder) { |
212 SleepMs(1 * rtc::kNumMillisecsPerSec); | 217 SleepMs(1 * rtc::kNumMillisecsPerSec); |
213 } | 218 } |
214 ReleaseAndCloseObjects(&task_queue); | 219 ReleaseAndCloseObjects(&task_queue); |
215 | 220 |
216 // Calculate and print rate control statistics. | 221 // Calculate and print rate control statistics. |
217 rate_update_index = 0; | 222 rate_update_index = 0; |
218 frame_number = 0; | 223 frame_number = 0; |
219 ResetRateControlMetrics(rate_update_index, rate_profile); | 224 ResetRateControlMetrics(rate_update_index, rate_profile); |
220 std::vector<int> num_dropped_frames; | 225 std::vector<int> num_dropped_frames; |
221 std::vector<int> num_resize_actions; | 226 std::vector<int> num_resize_actions; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
263 psnr_result.min, ssim_result.average, ssim_result.min); | 268 psnr_result.min, ssim_result.average, ssim_result.min); |
264 printf("\n"); | 269 printf("\n"); |
265 | 270 |
266 // Remove analysis file. | 271 // Remove analysis file. |
267 if (remove(config_.output_filename.c_str()) < 0) { | 272 if (remove(config_.output_filename.c_str()) < 0) { |
268 fprintf(stderr, "Failed to remove temporary file!\n"); | 273 fprintf(stderr, "Failed to remove temporary file!\n"); |
269 } | 274 } |
270 } | 275 } |
271 | 276 |
272 void VideoProcessorIntegrationTest::CreateEncoderAndDecoder() { | 277 void VideoProcessorIntegrationTest::CreateEncoderAndDecoder() { |
273 if (config_.hw_codec) { | 278 std::unique_ptr<cricket::WebRtcVideoEncoderFactory> encoder_factory; |
279 if (config_.hw_encoder) { | |
274 #if defined(WEBRTC_VIDEOPROCESSOR_INTEGRATIONTEST_HW_CODECS_ENABLED) | 280 #if defined(WEBRTC_VIDEOPROCESSOR_INTEGRATIONTEST_HW_CODECS_ENABLED) |
275 #if defined(WEBRTC_ANDROID) | 281 #if defined(WEBRTC_ANDROID) |
276 encoder_factory_.reset(new jni::MediaCodecVideoEncoderFactory()); | 282 encoder_factory.reset(new jni::MediaCodecVideoEncoderFactory()); |
283 #elif defined(WEBRTC_IOS) | |
284 EXPECT_EQ(kVideoCodecH264, config_.codec_settings.codecType) | |
285 << "iOS HW codecs only support H264."; | |
286 encoder_factory = CreateObjCEncoderFactory(); | |
287 #else | |
288 RTC_NOTREACHED() << "Only support HW encoder on Android and iOS."; | |
289 #endif | |
290 #endif // WEBRTC_VIDEOPROCESSOR_INTEGRATIONTEST_HW_CODECS_ENABLED | |
291 } else { | |
292 encoder_factory.reset(new cricket::InternalEncoderFactory()); | |
293 } | |
294 | |
295 if (config_.hw_decoder) { | |
296 #if defined(WEBRTC_VIDEOPROCESSOR_INTEGRATIONTEST_HW_CODECS_ENABLED) | |
297 #if defined(WEBRTC_ANDROID) | |
277 decoder_factory_.reset(new jni::MediaCodecVideoDecoderFactory()); | 298 decoder_factory_.reset(new jni::MediaCodecVideoDecoderFactory()); |
278 #elif defined(WEBRTC_IOS) | 299 #elif defined(WEBRTC_IOS) |
279 EXPECT_EQ(kVideoCodecH264, config_.codec_settings.codecType) | 300 EXPECT_EQ(kVideoCodecH264, config_.codec_settings.codecType) |
280 << "iOS HW codecs only support H264."; | 301 << "iOS HW codecs only support H264."; |
281 encoder_factory_ = CreateObjCEncoderFactory(); | |
282 decoder_factory_ = CreateObjCDecoderFactory(); | 302 decoder_factory_ = CreateObjCDecoderFactory(); |
283 #else | 303 #else |
284 RTC_NOTREACHED() << "Only support HW codecs on Android and iOS."; | 304 RTC_NOTREACHED() << "Only support HW decoder on Android and iOS."; |
285 #endif | 305 #endif |
286 #endif // WEBRTC_VIDEOPROCESSOR_INTEGRATIONTEST_HW_CODECS_ENABLED | 306 #endif // WEBRTC_VIDEOPROCESSOR_INTEGRATIONTEST_HW_CODECS_ENABLED |
287 } else { | 307 } else { |
288 // SW codecs. | |
289 encoder_factory_.reset(new cricket::InternalEncoderFactory()); | |
290 decoder_factory_.reset(new cricket::InternalDecoderFactory()); | 308 decoder_factory_.reset(new cricket::InternalDecoderFactory()); |
291 } | 309 } |
292 | 310 |
311 cricket::VideoCodec codec; | |
srte
2017/09/05 11:11:07
Since this seems to only be used for the encoder c
brandtr
2017/09/06 11:17:27
Done.
| |
293 switch (config_.codec_settings.codecType) { | 312 switch (config_.codec_settings.codecType) { |
294 case kVideoCodecVP8: | 313 case kVideoCodecVP8: |
295 encoder_ = encoder_factory_->CreateVideoEncoder( | 314 codec = cricket::VideoCodec(cricket::kVp8CodecName); |
296 cricket::VideoCodec(cricket::kVp8CodecName)); | 315 encoder_.reset(encoder_factory->CreateVideoEncoder(codec)); |
297 decoder_ = decoder_factory_->CreateVideoDecoder(kVideoCodecVP8); | 316 decoder_ = decoder_factory_->CreateVideoDecoder(kVideoCodecVP8); |
298 break; | 317 break; |
299 case kVideoCodecVP9: | 318 case kVideoCodecVP9: |
300 encoder_ = encoder_factory_->CreateVideoEncoder( | 319 codec = cricket::VideoCodec(cricket::kVp9CodecName); |
301 cricket::VideoCodec(cricket::kVp9CodecName)); | 320 encoder_.reset(encoder_factory->CreateVideoEncoder(codec)); |
302 decoder_ = decoder_factory_->CreateVideoDecoder(kVideoCodecVP9); | 321 decoder_ = decoder_factory_->CreateVideoDecoder(kVideoCodecVP9); |
303 break; | 322 break; |
304 case kVideoCodecH264: | 323 case kVideoCodecH264: |
305 // TODO(brandtr): Generalize so that we support multiple profiles here. | 324 // TODO(brandtr): Generalize so that we support multiple profiles here. |
306 encoder_ = encoder_factory_->CreateVideoEncoder( | 325 codec = cricket::VideoCodec(cricket::kH264CodecName); |
307 cricket::VideoCodec(cricket::kH264CodecName)); | 326 encoder_.reset(encoder_factory->CreateVideoEncoder(codec)); |
308 decoder_ = decoder_factory_->CreateVideoDecoder(kVideoCodecH264); | 327 decoder_ = decoder_factory_->CreateVideoDecoder(kVideoCodecH264); |
309 break; | 328 break; |
310 default: | 329 default: |
311 RTC_NOTREACHED(); | 330 RTC_NOTREACHED(); |
312 break; | 331 break; |
313 } | 332 } |
314 | 333 |
334 if (config_.sw_fallback_encoder) { | |
335 encoder_ = rtc::MakeUnique<VideoEncoderSoftwareFallbackWrapper>( | |
336 codec, std::move(encoder_)); | |
337 } | |
338 | |
315 EXPECT_TRUE(encoder_) << "Encoder not successfully created."; | 339 EXPECT_TRUE(encoder_) << "Encoder not successfully created."; |
316 EXPECT_TRUE(decoder_) << "Decoder not successfully created."; | 340 EXPECT_TRUE(decoder_) << "Decoder not successfully created."; |
317 } | 341 } |
318 | 342 |
319 void VideoProcessorIntegrationTest::DestroyEncoderAndDecoder() { | 343 void VideoProcessorIntegrationTest::DestroyEncoderAndDecoder() { |
320 encoder_factory_->DestroyVideoEncoder(encoder_); | 344 encoder_.reset(); |
321 decoder_factory_->DestroyVideoDecoder(decoder_); | 345 decoder_factory_->DestroyVideoDecoder(decoder_); |
322 } | 346 } |
323 | 347 |
324 void VideoProcessorIntegrationTest::SetUpAndInitObjects( | 348 void VideoProcessorIntegrationTest::SetUpAndInitObjects( |
325 rtc::TaskQueue* task_queue, | 349 rtc::TaskQueue* task_queue, |
326 const int initial_bitrate_kbps, | 350 const int initial_bitrate_kbps, |
327 const int initial_framerate_fps, | 351 const int initial_framerate_fps, |
328 const VisualizationParams* visualization_params) { | 352 const VisualizationParams* visualization_params) { |
329 CreateEncoderAndDecoder(); | 353 CreateEncoderAndDecoder(); |
330 | 354 |
331 // Create file objects for quality analysis. | 355 // Create file objects for quality analysis. |
332 analysis_frame_reader_.reset(new YuvFrameReaderImpl( | 356 analysis_frame_reader_.reset(new YuvFrameReaderImpl( |
333 config_.input_filename, config_.codec_settings.width, | 357 config_.input_filename, config_.codec_settings.width, |
334 config_.codec_settings.height)); | 358 config_.codec_settings.height)); |
335 analysis_frame_writer_.reset(new YuvFrameWriterImpl( | 359 analysis_frame_writer_.reset(new YuvFrameWriterImpl( |
336 config_.output_filename, config_.codec_settings.width, | 360 config_.output_filename, config_.codec_settings.width, |
337 config_.codec_settings.height)); | 361 config_.codec_settings.height)); |
338 EXPECT_TRUE(analysis_frame_reader_->Init()); | 362 EXPECT_TRUE(analysis_frame_reader_->Init()); |
339 EXPECT_TRUE(analysis_frame_writer_->Init()); | 363 EXPECT_TRUE(analysis_frame_writer_->Init()); |
340 | 364 |
341 if (visualization_params) { | 365 if (visualization_params) { |
342 const std::string codec_name = | 366 const std::string codec_name = |
343 CodecTypeToPayloadString(config_.codec_settings.codecType); | 367 CodecTypeToPayloadString(config_.codec_settings.codecType); |
344 const std::string implementation_type = config_.hw_codec ? "hw" : "sw"; | 368 const std::string implementation_type = config_.hw_encoder ? "hw" : "sw"; |
345 // clang-format off | 369 // clang-format off |
346 const std::string output_filename_base = | 370 const std::string output_filename_base = |
347 OutputPath() + config_.filename + "-" + | 371 OutputPath() + config_.filename + "-" + |
348 codec_name + "-" + implementation_type + "-" + | 372 codec_name + "-" + implementation_type + "-" + |
349 std::to_string(initial_bitrate_kbps); | 373 std::to_string(initial_bitrate_kbps); |
350 // clang-format on | 374 // clang-format on |
351 if (visualization_params->save_encoded_ivf) { | 375 if (visualization_params->save_encoded_ivf) { |
352 rtc::File post_encode_file = | 376 rtc::File post_encode_file = |
353 rtc::File::Create(output_filename_base + ".ivf"); | 377 rtc::File::Create(output_filename_base + ".ivf"); |
354 encoded_frame_writer_ = | 378 encoded_frame_writer_ = |
(...skipping 10 matching lines...) Expand all Loading... | |
365 packet_manipulator_.reset(new PacketManipulatorImpl( | 389 packet_manipulator_.reset(new PacketManipulatorImpl( |
366 &packet_reader_, config_.networking_config, config_.verbose)); | 390 &packet_reader_, config_.networking_config, config_.verbose)); |
367 | 391 |
368 config_.codec_settings.minBitrate = 0; | 392 config_.codec_settings.minBitrate = 0; |
369 config_.codec_settings.startBitrate = initial_bitrate_kbps; | 393 config_.codec_settings.startBitrate = initial_bitrate_kbps; |
370 config_.codec_settings.maxFramerate = initial_framerate_fps; | 394 config_.codec_settings.maxFramerate = initial_framerate_fps; |
371 | 395 |
372 rtc::Event sync_event(false, false); | 396 rtc::Event sync_event(false, false); |
373 task_queue->PostTask([this, &sync_event]() { | 397 task_queue->PostTask([this, &sync_event]() { |
374 processor_ = rtc::MakeUnique<VideoProcessor>( | 398 processor_ = rtc::MakeUnique<VideoProcessor>( |
375 encoder_, decoder_, analysis_frame_reader_.get(), | 399 encoder_.get(), decoder_, analysis_frame_reader_.get(), |
srte
2017/09/05 11:11:07
Somewhat dangerous call to .get() here, just make
brandtr
2017/09/06 11:17:27
Yes, the lifetime of the objects passed in here ne
| |
376 analysis_frame_writer_.get(), packet_manipulator_.get(), config_, | 400 analysis_frame_writer_.get(), packet_manipulator_.get(), config_, |
377 &stats_, encoded_frame_writer_.get(), decoded_frame_writer_.get()); | 401 &stats_, encoded_frame_writer_.get(), decoded_frame_writer_.get()); |
378 processor_->Init(); | 402 processor_->Init(); |
379 sync_event.Set(); | 403 sync_event.Set(); |
380 }); | 404 }); |
381 sync_event.Wait(rtc::Event::kForever); | 405 sync_event.Wait(rtc::Event::kForever); |
382 } | 406 } |
383 | 407 |
384 void VideoProcessorIntegrationTest::ReleaseAndCloseObjects( | 408 void VideoProcessorIntegrationTest::ReleaseAndCloseObjects( |
385 rtc::TaskQueue* task_queue) { | 409 rtc::TaskQueue* task_queue) { |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
621 perc_encoding_rate_mismatch_ = 0.0f; | 645 perc_encoding_rate_mismatch_ = 0.0f; |
622 num_frames_to_hit_target_ = | 646 num_frames_to_hit_target_ = |
623 rate_profile.frame_index_rate_update[rate_update_index + 1]; | 647 rate_profile.frame_index_rate_update[rate_update_index + 1]; |
624 encoding_rate_within_target_ = false; | 648 encoding_rate_within_target_ = false; |
625 sum_key_frame_size_mismatch_ = 0.0; | 649 sum_key_frame_size_mismatch_ = 0.0; |
626 num_key_frames_ = 0; | 650 num_key_frames_ = 0; |
627 } | 651 } |
628 | 652 |
629 } // namespace test | 653 } // namespace test |
630 } // namespace webrtc | 654 } // namespace webrtc |
OLD | NEW |