From 6bb8e0efd3187e11ac512d84d665b4cffacad43e Mon Sep 17 00:00:00 2001 From: brandtr Date: Mon, 20 Feb 2017 04:35:52 -0800 Subject: [PATCH] Add support for creating HW codecs in the VideoProcessor tests. This CL adds the ability to _create_ HW codecs (Android and iOS) in the VideoProcessor integration tests. Since the VideoProcessor class is not thread safe yet, this CL does not add the ability to _use_ HW codecs in the tests. A follow-up CL is planned that will add this ability. This CL further adds a separate build target which is used to separate the "plot" versions of the integration tests from the "correctness" versions. The former will be run manually on devices, whereas the latter are used on the trybots/buildbots to find regressions in the SW codecs. The underlying test is the same, however. BUG=webrtc:6634 Review-Url: https://codereview.webrtc.org/2695653002 Cr-Commit-Position: refs/heads/master@{#16716} --- resources/foreman_128x96.yuv.sha1 | 1 + resources/foreman_160x120.yuv.sha1 | 1 + resources/foreman_176x144.yuv.sha1 | 1 + resources/foreman_320x240.yuv.sha1 | 1 + webrtc/modules/video_coding/BUILD.gn | 115 +++++++++++++++++- webrtc/modules/video_coding/DEPS | 11 ++ .../codecs/test/android_test_initializer.cc | 55 +++++++++ .../codecs/test/android_test_initializer.h | 20 +++ .../plot_videoprocessor_integrationtest.cc | 13 +- .../codecs/test/videoprocessor.cc | 16 ++- .../video_coding/codecs/test/videoprocessor.h | 8 +- .../test/videoprocessor_integrationtest.cc | 59 +++++---- .../test/videoprocessor_integrationtest.h | 98 ++++++++++++--- 13 files changed, 341 insertions(+), 58 deletions(-) create mode 100644 resources/foreman_128x96.yuv.sha1 create mode 100644 resources/foreman_160x120.yuv.sha1 create mode 100644 resources/foreman_176x144.yuv.sha1 create mode 100644 resources/foreman_320x240.yuv.sha1 create mode 100644 webrtc/modules/video_coding/codecs/test/android_test_initializer.cc create mode 100644 webrtc/modules/video_coding/codecs/test/android_test_initializer.h diff --git a/resources/foreman_128x96.yuv.sha1 b/resources/foreman_128x96.yuv.sha1 new file mode 100644 index 0000000000..0299f5acb4 --- /dev/null +++ b/resources/foreman_128x96.yuv.sha1 @@ -0,0 +1 @@ +bf2fe75c6921c2be9c8cfd1cc00c6540133a2931 \ No newline at end of file diff --git a/resources/foreman_160x120.yuv.sha1 b/resources/foreman_160x120.yuv.sha1 new file mode 100644 index 0000000000..8a932f91bc --- /dev/null +++ b/resources/foreman_160x120.yuv.sha1 @@ -0,0 +1 @@ +315d8a7cc06fe15b68a6f2106d59d25b16270552 \ No newline at end of file diff --git a/resources/foreman_176x144.yuv.sha1 b/resources/foreman_176x144.yuv.sha1 new file mode 100644 index 0000000000..d728721257 --- /dev/null +++ b/resources/foreman_176x144.yuv.sha1 @@ -0,0 +1 @@ +4a38b5629845646844350a4257a60554888509b9 \ No newline at end of file diff --git a/resources/foreman_320x240.yuv.sha1 b/resources/foreman_320x240.yuv.sha1 new file mode 100644 index 0000000000..5dae3f8bab --- /dev/null +++ b/resources/foreman_320x240.yuv.sha1 @@ -0,0 +1 @@ +bb838d60f2a0454af4ca63735d573069858ec004 \ No newline at end of file diff --git a/webrtc/modules/video_coding/BUILD.gn b/webrtc/modules/video_coding/BUILD.gn index a3ad4b37c7..e8ac6719ab 100644 --- a/webrtc/modules/video_coding/BUILD.gn +++ b/webrtc/modules/video_coding/BUILD.gn @@ -341,13 +341,13 @@ if (rtc_include_tests) { ] } - rtc_source_set("video_coding_modules_tests") { + rtc_source_set("video_coding_videoprocessor_integration_test") { testonly = true + sources = [ - "codecs/test/videoprocessor_integrationtest.cc", "codecs/test/videoprocessor_integrationtest.h", - "codecs/vp8/test/vp8_impl_unittest.cc", ] + deps = [ ":video_codecs_test_framework", ":video_coding", @@ -355,18 +355,123 @@ if (rtc_include_tests) { ":webrtc_vp8", ":webrtc_vp9", "../..:webrtc_common", + "../../base:rtc_base_approved", + "../../media:rtc_media", + "../../test:test_support", + "../../test:video_test_support", + ] + + if (is_android) { + sources += [ + "codecs/test/android_test_initializer.cc", + "codecs/test/android_test_initializer.h", + ] + + deps += [ + "../../base:rtc_base_approved", + "../../sdk/android:libjingle_peerconnection_jni", + "//base", + ] + } + + if (is_ios || is_mac) { + deps += [ + "../../media:rtc_media_base", + "../../sdk:webrtc_h264_video_toolbox", + ] + } + } + + rtc_source_set("video_coding_modules_tests") { + testonly = true + + sources = [ + "codecs/test/videoprocessor_integrationtest.cc", + "codecs/vp8/test/vp8_impl_unittest.cc", + ] + + deps = [ + ":video_coding_videoprocessor_integration_test", + ":webrtc_vp8", "../../api:video_frame_api", "../../base:rtc_base_approved", "../../common_video:common_video", - "../../media:rtc_media_base", "../../test:test_support", "../../test:video_test_common", - "../../test:video_test_support", "../video_capture", ] + if (rtc_use_h264) { defines = [ "WEBRTC_VIDEOPROCESSOR_H264_TESTS" ] } + + if (!build_with_chromium && is_clang) { + # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163). + suppressed_configs += [ "//build/config/clang:find_bad_constructs" ] + } + } + + plot_videoprocessor_integrationtest_resources = [ + "//resources/foreman_128x96.yuv", + "//resources/foreman_160x120.yuv", + "//resources/foreman_176x144.yuv", + "//resources/foreman_320x240.yuv", + "//resources/foreman_cif.yuv", + ] + + if (is_ios || is_mac) { + bundle_data("plot_videoprocessor_integrationtest_bundle_data") { + testonly = true + sources = plot_videoprocessor_integrationtest_resources + outputs = [ + "{{bundle_resources_dir}}/{{source_file_part}}", + ] + } + } + + # This executable is meant for local codec perf testing and should not be run + # on the trybots/buildbots, hence the existence of this special build target. + rtc_test("plot_videoprocessor_integrationtest") { + testonly = true + + sources = [ + "codecs/test/plot_videoprocessor_integrationtest.cc", + ] + + deps = [ + ":video_coding_videoprocessor_integration_test", + "../../test:test_main", + "../../test:video_test_common", + "../video_capture", + ] + + data = plot_videoprocessor_integrationtest_resources + + if (is_android) { + deps += [ + "../../base:rtc_base_approved", + + # TODO(brandtr): Figure out if the java dep below could be moved into + # :video_coding_videoprocessor_integration_test, where it belongs. + # When that is done, support for Android HW codecs can be added to the + # modules_tests target as well. + "../../sdk/android:libjingle_peerconnection_java", + "../../sdk/android:libjingle_peerconnection_jni", + "//base", + "//testing/android/native_test:native_test_support", + ] + + shard_timeout = 900 + } + + if (is_ios || is_mac) { + deps += [ ":plot_videoprocessor_integrationtest_bundle_data" ] + } + + # TODO(brandtr): Remove this define when the modules_tests target properly + # loads the Java classes mentioned above. + defines = [ "WEBRTC_VIDEOPROCESSOR_INTEGRATIONTEST_HW_CODECS_ENABLED" ] + if (!build_with_chromium && is_clang) { # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163). suppressed_configs += [ "//build/config/clang:find_bad_constructs" ] diff --git a/webrtc/modules/video_coding/DEPS b/webrtc/modules/video_coding/DEPS index d8e3c22cd6..01cd4d574d 100644 --- a/webrtc/modules/video_coding/DEPS +++ b/webrtc/modules/video_coding/DEPS @@ -8,3 +8,14 @@ include_rules = [ "+webrtc/system_wrappers", "+webrtc/tools", ] + +specific_include_rules = { + "android_test_initializer\.cc": [ + "+base/android", + "+webrtc/sdk", + ], + "(.*test\.cc|.*test\.h)": [ + "+webrtc/media/engine", + "+webrtc/sdk", + ], +} diff --git a/webrtc/modules/video_coding/codecs/test/android_test_initializer.cc b/webrtc/modules/video_coding/codecs/test/android_test_initializer.cc new file mode 100644 index 0000000000..cb2c5c1f5b --- /dev/null +++ b/webrtc/modules/video_coding/codecs/test/android_test_initializer.cc @@ -0,0 +1,55 @@ +/* + * Copyright 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include + +#include "webrtc/base/ignore_wundef.h" +#include "webrtc/modules/video_coding/codecs/test/android_test_initializer.h" +#include "webrtc/sdk/android/src/jni/classreferenceholder.h" +#include "webrtc/sdk/android/src/jni/jni_helpers.h" + +// Note: this dependency is dangerous since it reaches into Chromium's base. +// There's a risk of e.g. macro clashes. This file may only be used in tests. +// Since we use Chrome's build system for creating the gtest binary, this should +// be fine. +RTC_PUSH_IGNORING_WUNDEF() +#include "base/android/jni_android.h" +RTC_POP_IGNORING_WUNDEF() + +#include "webrtc/base/checks.h" + +namespace webrtc { + +namespace { + +static pthread_once_t g_initialize_once = PTHREAD_ONCE_INIT; + +// There can only be one JNI_OnLoad in each binary. So since this is a GTEST +// C++ runner binary, we want to initialize the same global objects we normally +// do if this had been a Java binary. +void EnsureInitializedOnce() { + RTC_CHECK(::base::android::IsVMInitialized()); + JNIEnv* jni = ::base::android::AttachCurrentThread(); + JavaVM* jvm = NULL; + RTC_CHECK_EQ(0, jni->GetJavaVM(&jvm)); + + jint ret = webrtc_jni::InitGlobalJniVariables(jvm); + RTC_DCHECK_GE(ret, 0); + + webrtc_jni::LoadGlobalClassReferenceHolder(); +} + +} // namespace + +void InitializeAndroidObjects() { + RTC_CHECK_EQ(0, pthread_once(&g_initialize_once, &EnsureInitializedOnce)); +} + +} // namespace webrtc diff --git a/webrtc/modules/video_coding/codecs/test/android_test_initializer.h b/webrtc/modules/video_coding/codecs/test/android_test_initializer.h new file mode 100644 index 0000000000..a4ec9d2012 --- /dev/null +++ b/webrtc/modules/video_coding/codecs/test/android_test_initializer.h @@ -0,0 +1,20 @@ +/* + * Copyright 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_ANDROID_TEST_INITIALIZER_H_ +#define WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_ANDROID_TEST_INITIALIZER_H_ + +namespace webrtc { + +void InitializeAndroidObjects(); + +} // namespace webrtc + +#endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_ANDROID_TEST_INITIALIZER_H_ diff --git a/webrtc/modules/video_coding/codecs/test/plot_videoprocessor_integrationtest.cc b/webrtc/modules/video_coding/codecs/test/plot_videoprocessor_integrationtest.cc index d4152e0c74..f265230607 100644 --- a/webrtc/modules/video_coding/codecs/test/plot_videoprocessor_integrationtest.cc +++ b/webrtc/modules/video_coding/codecs/test/plot_videoprocessor_integrationtest.cc @@ -21,6 +21,7 @@ const bool kDenoisingOn = false; const bool kFrameDropperOn = true; const bool kSpatialResizeOn = false; const VideoCodecType kVideoCodecType[] = {kVideoCodecVP8}; +const bool kHwCodec = false; // Packet loss probability [0.0, 1.0]. const float kPacketLoss = 0.0f; @@ -52,7 +53,7 @@ class PlotVideoProcessorIntegrationTest rate_profile.num_frames = kNumFramesLong; // Codec/network settings. CodecConfigPars process_settings; - SetCodecParameters(&process_settings, codec_type_, kPacketLoss, + SetCodecParameters(&process_settings, codec_type_, kHwCodec, kPacketLoss, -1, // key_frame_interval 1, // num_temporal_layers kErrorConcealmentOn, kDenoisingOn, kFrameDropperOn, @@ -87,23 +88,23 @@ INSTANTIATE_TEST_CASE_P( ::testing::ValuesIn(kFps), ::testing::ValuesIn(kVideoCodecType))); -TEST_P(PlotVideoProcessorIntegrationTest, ProcessSQCif) { +TEST_P(PlotVideoProcessorIntegrationTest, Process128x96) { RunTest(128, 96, "foreman_128x96"); } -TEST_P(PlotVideoProcessorIntegrationTest, ProcessQQVga) { +TEST_P(PlotVideoProcessorIntegrationTest, Process160x120) { RunTest(160, 120, "foreman_160x120"); } -TEST_P(PlotVideoProcessorIntegrationTest, ProcessQCif) { +TEST_P(PlotVideoProcessorIntegrationTest, Process176x144) { RunTest(176, 144, "foreman_176x144"); } -TEST_P(PlotVideoProcessorIntegrationTest, ProcessQVga) { +TEST_P(PlotVideoProcessorIntegrationTest, Process320x240) { RunTest(320, 240, "foreman_320x240"); } -TEST_P(PlotVideoProcessorIntegrationTest, ProcessCif) { +TEST_P(PlotVideoProcessorIntegrationTest, Process352x288) { RunTest(352, 288, "foreman_cif"); } diff --git a/webrtc/modules/video_coding/codecs/test/videoprocessor.cc b/webrtc/modules/video_coding/codecs/test/videoprocessor.cc index cd07a866a6..2acc8484e2 100644 --- a/webrtc/modules/video_coding/codecs/test/videoprocessor.cc +++ b/webrtc/modules/video_coding/codecs/test/videoprocessor.cc @@ -374,7 +374,11 @@ void VideoProcessorImpl::FrameDecoded(const VideoFrame& image) { config_.codec_settings->height)); // Should be the same aspect ratio, no cropping needed. - up_image->ScaleFrom(*image.video_frame_buffer()); + if (image.video_frame_buffer()->native_handle()) { + up_image->ScaleFrom(*image.video_frame_buffer()->NativeToI420Buffer()); + } else { + up_image->ScaleFrom(*image.video_frame_buffer()); + } // TODO(mikhal): Extracting the buffer for now - need to update test. size_t length = @@ -395,7 +399,15 @@ void VideoProcessorImpl::FrameDecoded(const VideoFrame& image) { // TODO(mikhal): Add as a member function, so won't be allocated per frame. size_t length = CalcBufferSize(kI420, image.width(), image.height()); std::unique_ptr image_buffer(new uint8_t[length]); - int extracted_length = ExtractBuffer(image, length, image_buffer.get()); + int extracted_length; + if (image.video_frame_buffer()->native_handle()) { + extracted_length = + ExtractBuffer(image.video_frame_buffer()->NativeToI420Buffer(), + length, image_buffer.get()); + } else { + extracted_length = + ExtractBuffer(image.video_frame_buffer(), length, image_buffer.get()); + } RTC_DCHECK_GT(extracted_length, 0); memcpy(last_successful_frame_buffer_.get(), image_buffer.get(), extracted_length); diff --git a/webrtc/modules/video_coding/codecs/test/videoprocessor.h b/webrtc/modules/video_coding/codecs/test/videoprocessor.h index 736acc64c0..de20020bdc 100644 --- a/webrtc/modules/video_coding/codecs/test/videoprocessor.h +++ b/webrtc/modules/video_coding/codecs/test/videoprocessor.h @@ -205,13 +205,13 @@ class VideoProcessorImpl : public VideoProcessor { } int32_t Decoded(webrtc::VideoFrame& image, int64_t decode_time_ms) override { - RTC_NOTREACHED(); - return -1; + return Decoded(image); } - void Decoded(VideoFrame& frame, + void Decoded(webrtc::VideoFrame& image, rtc::Optional decode_time_ms, rtc::Optional qp) override { - RTC_NOTREACHED(); + Decoded(image, + decode_time_ms ? static_cast(*decode_time_ms) : -1); } private: diff --git a/webrtc/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc b/webrtc/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc index 841303e7e4..cb2315db3d 100644 --- a/webrtc/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc +++ b/webrtc/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc @@ -13,6 +13,13 @@ namespace webrtc { namespace test { +namespace { + +// In these correctness tests, we only consider SW codecs. +const bool kHwCodec = false; + +} // namespace + #if defined(WEBRTC_VIDEOPROCESSOR_H264_TESTS) // H264: Run with no packet loss and fixed bitrate. Quality should be very high. @@ -28,8 +35,8 @@ TEST_F(VideoProcessorIntegrationTest, Process0PercentPacketLossH264) { rate_profile.num_frames = kNumFramesShort; // Codec/network settings. CodecConfigPars process_settings; - SetCodecParameters(&process_settings, kVideoCodecH264, 0.0f, -1, 1, false, - false, true, false); + SetCodecParameters(&process_settings, kVideoCodecH264, kHwCodec, 0.0f, -1, 1, + false, false, true, false); // Metrics for expected quality. QualityMetrics quality_metrics; SetQualityMetrics(&quality_metrics, 35.0, 25.0, 0.93, 0.70); @@ -59,8 +66,8 @@ TEST_F(VideoProcessorIntegrationTest, Process0PercentPacketLossVP9) { rate_profile.num_frames = kNumFramesShort; // Codec/network settings. CodecConfigPars process_settings; - SetCodecParameters(&process_settings, kVideoCodecVP9, 0.0f, -1, 1, false, - false, true, false); + SetCodecParameters(&process_settings, kVideoCodecVP9, kHwCodec, 0.0f, -1, 1, + false, false, true, false); // Metrics for expected quality. QualityMetrics quality_metrics; SetQualityMetrics(&quality_metrics, 37.0, 36.0, 0.93, 0.92); @@ -81,8 +88,8 @@ TEST_F(VideoProcessorIntegrationTest, Process5PercentPacketLossVP9) { rate_profile.num_frames = kNumFramesShort; // Codec/network settings. CodecConfigPars process_settings; - SetCodecParameters(&process_settings, kVideoCodecVP9, 0.05f, -1, 1, false, - false, true, false); + SetCodecParameters(&process_settings, kVideoCodecVP9, kHwCodec, 0.05f, -1, 1, + false, false, true, false); // Metrics for expected quality. QualityMetrics quality_metrics; SetQualityMetrics(&quality_metrics, 17.0, 14.0, 0.45, 0.36); @@ -107,8 +114,8 @@ TEST_F(VideoProcessorIntegrationTest, ProcessNoLossChangeBitRateVP9) { rate_profile.num_frames = kNumFramesLong; // Codec/network settings. CodecConfigPars process_settings; - SetCodecParameters(&process_settings, kVideoCodecVP9, 0.0f, -1, 1, false, - false, true, false); + SetCodecParameters(&process_settings, kVideoCodecVP9, kHwCodec, 0.0f, -1, 1, + false, false, true, false); // Metrics for expected quality. QualityMetrics quality_metrics; SetQualityMetrics(&quality_metrics, 35.5, 30.0, 0.90, 0.85); @@ -140,8 +147,8 @@ TEST_F(VideoProcessorIntegrationTest, rate_profile.num_frames = kNumFramesLong; // Codec/network settings. CodecConfigPars process_settings; - SetCodecParameters(&process_settings, kVideoCodecVP9, 0.0f, -1, 1, false, - false, true, false); + SetCodecParameters(&process_settings, kVideoCodecVP9, kHwCodec, 0.0f, -1, 1, + false, false, true, false); // Metrics for expected quality. QualityMetrics quality_metrics; SetQualityMetrics(&quality_metrics, 31.5, 18.0, 0.80, 0.43); @@ -163,8 +170,8 @@ TEST_F(VideoProcessorIntegrationTest, ProcessNoLossDenoiserOnVP9) { rate_profile.num_frames = kNumFramesShort; // Codec/network settings. CodecConfigPars process_settings; - SetCodecParameters(&process_settings, kVideoCodecVP9, 0.0f, -1, 1, false, - true, true, false); + SetCodecParameters(&process_settings, kVideoCodecVP9, kHwCodec, 0.0f, -1, 1, + false, true, true, false); // Metrics for expected quality. QualityMetrics quality_metrics; SetQualityMetrics(&quality_metrics, 36.8, 35.8, 0.92, 0.91); @@ -188,8 +195,8 @@ TEST_F(VideoProcessorIntegrationTest, rate_profile.num_frames = kNumFramesLong; // Codec/network settings. CodecConfigPars process_settings; - SetCodecParameters(&process_settings, kVideoCodecVP9, 0.0f, -1, 1, false, - false, true, true); + SetCodecParameters(&process_settings, kVideoCodecVP9, kHwCodec, 0.0f, -1, 1, + false, false, true, true); // Metrics for expected quality. QualityMetrics quality_metrics; SetQualityMetrics(&quality_metrics, 24.0, 13.0, 0.65, 0.37); @@ -216,8 +223,8 @@ TEST_F(VideoProcessorIntegrationTest, ProcessZeroPacketLoss) { rate_profile.num_frames = kNumFramesShort; // Codec/network settings. CodecConfigPars process_settings; - SetCodecParameters(&process_settings, kVideoCodecVP8, 0.0f, -1, 1, false, - true, true, false); + SetCodecParameters(&process_settings, kVideoCodecVP8, kHwCodec, 0.0f, -1, 1, + false, true, true, false); // Metrics for expected quality. QualityMetrics quality_metrics; SetQualityMetrics(&quality_metrics, 34.95, 33.0, 0.90, 0.89); @@ -238,8 +245,8 @@ TEST_F(VideoProcessorIntegrationTest, Process5PercentPacketLoss) { rate_profile.num_frames = kNumFramesShort; // Codec/network settings. CodecConfigPars process_settings; - SetCodecParameters(&process_settings, kVideoCodecVP8, 0.05f, -1, 1, false, - true, true, false); + SetCodecParameters(&process_settings, kVideoCodecVP8, kHwCodec, 0.05f, -1, 1, + false, true, true, false); // Metrics for expected quality. QualityMetrics quality_metrics; SetQualityMetrics(&quality_metrics, 20.0, 16.0, 0.60, 0.40); @@ -260,8 +267,8 @@ TEST_F(VideoProcessorIntegrationTest, Process10PercentPacketLoss) { rate_profile.num_frames = kNumFramesShort; // Codec/network settings. CodecConfigPars process_settings; - SetCodecParameters(&process_settings, kVideoCodecVP8, 0.1f, -1, 1, false, - true, true, false); + SetCodecParameters(&process_settings, kVideoCodecVP8, kHwCodec, 0.1f, -1, 1, + false, true, true, false); // Metrics for expected quality. QualityMetrics quality_metrics; SetQualityMetrics(&quality_metrics, 19.0, 16.0, 0.50, 0.35); @@ -304,8 +311,8 @@ TEST_F(VideoProcessorIntegrationTest, MAYBE_ProcessNoLossChangeBitRateVP8) { rate_profile.num_frames = kNumFramesLong; // Codec/network settings. CodecConfigPars process_settings; - SetCodecParameters(&process_settings, kVideoCodecVP8, 0.0f, -1, 1, false, - true, true, false); + SetCodecParameters(&process_settings, kVideoCodecVP8, kHwCodec, 0.0f, -1, 1, + false, true, true, false); // Metrics for expected quality. QualityMetrics quality_metrics; SetQualityMetrics(&quality_metrics, 34.0, 32.0, 0.85, 0.80); @@ -345,8 +352,8 @@ TEST_F(VideoProcessorIntegrationTest, rate_profile.num_frames = kNumFramesLong; // Codec/network settings. CodecConfigPars process_settings; - SetCodecParameters(&process_settings, kVideoCodecVP8, 0.0f, -1, 1, false, - true, true, false); + SetCodecParameters(&process_settings, kVideoCodecVP8, kHwCodec, 0.0f, -1, 1, + false, true, true, false); // Metrics for expected quality. QualityMetrics quality_metrics; SetQualityMetrics(&quality_metrics, 31.0, 22.0, 0.80, 0.65); @@ -381,8 +388,8 @@ TEST_F(VideoProcessorIntegrationTest, MAYBE_ProcessNoLossTemporalLayersVP8) { rate_profile.num_frames = kNumFramesLong; // Codec/network settings. CodecConfigPars process_settings; - SetCodecParameters(&process_settings, kVideoCodecVP8, 0.0f, -1, 3, false, - true, true, false); + SetCodecParameters(&process_settings, kVideoCodecVP8, kHwCodec, 0.0f, -1, 3, + false, true, true, false); // Metrics for expected quality. QualityMetrics quality_metrics; SetQualityMetrics(&quality_metrics, 32.5, 30.0, 0.85, 0.80); diff --git a/webrtc/modules/video_coding/codecs/test/videoprocessor_integrationtest.h b/webrtc/modules/video_coding/codecs/test/videoprocessor_integrationtest.h index 54700c1b53..e1c085ed43 100644 --- a/webrtc/modules/video_coding/codecs/test/videoprocessor_integrationtest.h +++ b/webrtc/modules/video_coding/codecs/test/videoprocessor_integrationtest.h @@ -16,7 +16,18 @@ #include #include +#if defined(WEBRTC_ANDROID) +#include "webrtc/modules/video_coding/codecs/test/android_test_initializer.h" +#include "webrtc/sdk/android/src/jni/androidmediadecoder_jni.h" +#include "webrtc/sdk/android/src/jni/androidmediaencoder_jni.h" +#elif defined(WEBRTC_IOS) +#include "webrtc/sdk/objc/Framework/Classes/h264_video_toolbox_decoder.h" +#include "webrtc/sdk/objc/Framework/Classes/h264_video_toolbox_encoder.h" +#endif + #include "webrtc/base/checks.h" +#include "webrtc/media/engine/webrtcvideodecoderfactory.h" +#include "webrtc/media/engine/webrtcvideoencoderfactory.h" #include "webrtc/modules/video_coding/codecs/h264/include/h264.h" #include "webrtc/modules/video_coding/codecs/test/packet_manipulator.h" #include "webrtc/modules/video_coding/codecs/test/videoprocessor.h" @@ -51,6 +62,7 @@ const char kFilenameForemanCif[] = "foreman_cif"; // Codec and network settings. struct CodecConfigPars { VideoCodecType codec_type; + bool hw_codec; float packet_loss; int num_temporal_layers; int key_frame_interval; @@ -117,27 +129,75 @@ const float kScaleKeyFrameSize = 0.5f; // happen when some significant regression or breakdown occurs. class VideoProcessorIntegrationTest : public testing::Test { protected: - VideoProcessorIntegrationTest() {} - virtual ~VideoProcessorIntegrationTest() {} + VideoProcessorIntegrationTest() { +#if defined(WEBRTC_VIDEOPROCESSOR_INTEGRATIONTEST_HW_CODECS_ENABLED) && \ + defined(WEBRTC_ANDROID) + InitializeAndroidObjects(); + + external_encoder_factory_.reset( + new webrtc_jni::MediaCodecVideoEncoderFactory()); + external_decoder_factory_.reset( + new webrtc_jni::MediaCodecVideoDecoderFactory()); +#endif + } + virtual ~VideoProcessorIntegrationTest() = default; void SetUpCodecConfig(const std::string& filename, int width, int height, bool verbose_logging) { - if (codec_type_ == kVideoCodecH264) { - encoder_.reset(H264Encoder::Create(cricket::VideoCodec("H264"))); - decoder_.reset(H264Decoder::Create()); - VideoCodingModule::Codec(kVideoCodecH264, &codec_settings_); - } else if (codec_type_ == kVideoCodecVP8) { - encoder_.reset(VP8Encoder::Create()); - decoder_.reset(VP8Decoder::Create()); - VideoCodingModule::Codec(kVideoCodecVP8, &codec_settings_); - } else if (codec_type_ == kVideoCodecVP9) { - encoder_.reset(VP9Encoder::Create()); - decoder_.reset(VP9Decoder::Create()); - VideoCodingModule::Codec(kVideoCodecVP9, &codec_settings_); + if (hw_codec_) { +#if defined(WEBRTC_VIDEOPROCESSOR_INTEGRATIONTEST_HW_CODECS_ENABLED) +#if defined(WEBRTC_ANDROID) + // In general, external codecs should be destroyed by the factories that + // allocated them. For the particular case of the Android + // MediaCodecVideo{En,De}coderFactory's, however, it turns out that it is + // fine for the std::unique_ptr to destroy the owned codec directly. + if (codec_type_ == kVideoCodecH264) { + encoder_.reset(external_encoder_factory_->CreateVideoEncoder( + cricket::VideoCodec(cricket::kH264CodecName))); + decoder_.reset( + external_decoder_factory_->CreateVideoDecoder(kVideoCodecH264)); + } else if (codec_type_ == kVideoCodecVP8) { + encoder_.reset(external_encoder_factory_->CreateVideoEncoder( + cricket::VideoCodec(cricket::kVp8CodecName))); + decoder_.reset( + external_decoder_factory_->CreateVideoDecoder(kVideoCodecVP8)); + } else if (codec_type_ == kVideoCodecVP9) { + encoder_.reset(external_encoder_factory_->CreateVideoEncoder( + cricket::VideoCodec(cricket::kVp9CodecName))); + decoder_.reset( + external_decoder_factory_->CreateVideoDecoder(kVideoCodecVP9)); + } +#elif defined(WEBRTC_IOS) + RTC_DCHECK_EQ(kVideoCodecH264, codec_type_) + << "iOS HW codecs only support H264."; + encoder_.reset(new H264VideoToolboxEncoder( + cricket::VideoCodec(cricket::kH264CodecName))); + decoder_.reset(new H264VideoToolboxDecoder()); +#else + RTC_NOTREACHED() << "Only support HW codecs on Android and iOS."; +#endif +#endif // WEBRTC_VIDEOPROCESSOR_INTEGRATIONTEST_HW_CODECS_ENABLED + RTC_DCHECK(encoder_) << "HW encoder not successfully created."; + RTC_DCHECK(decoder_) << "HW decoder not successfully created."; + } else { + // SW codecs. + if (codec_type_ == kVideoCodecH264) { + encoder_.reset( + H264Encoder::Create(cricket::VideoCodec(cricket::kH264CodecName))); + decoder_.reset(H264Decoder::Create()); + } else if (codec_type_ == kVideoCodecVP8) { + encoder_.reset(VP8Encoder::Create()); + decoder_.reset(VP8Decoder::Create()); + } else if (codec_type_ == kVideoCodecVP9) { + encoder_.reset(VP9Encoder::Create()); + decoder_.reset(VP9Decoder::Create()); + } } + VideoCodingModule::Codec(codec_type_, &codec_settings_); + // Configure input filename. config_.input_filename = test::ResourcePath(filename, "yuv"); if (verbose_logging) @@ -389,6 +449,7 @@ class VideoProcessorIntegrationTest : public testing::Test { RateControlMetrics* rc_metrics) { // Codec/config settings. codec_type_ = process.codec_type; + hw_codec_ = process.hw_codec; start_bitrate_ = rate_profile.target_bit_rate[0]; packet_loss_ = process.packet_loss; key_frame_interval_ = process.key_frame_interval; @@ -501,6 +562,7 @@ class VideoProcessorIntegrationTest : public testing::Test { static void SetCodecParameters(CodecConfigPars* process_settings, VideoCodecType codec_type, + bool hw_codec, float packet_loss, int key_frame_interval, int num_temporal_layers, @@ -513,6 +575,7 @@ class VideoProcessorIntegrationTest : public testing::Test { const std::string& filename, bool verbose_logging) { process_settings->codec_type = codec_type; + process_settings->hw_codec = hw_codec; process_settings->packet_loss = packet_loss; process_settings->key_frame_interval = key_frame_interval; process_settings->num_temporal_layers = num_temporal_layers, @@ -528,6 +591,7 @@ class VideoProcessorIntegrationTest : public testing::Test { static void SetCodecParameters(CodecConfigPars* process_settings, VideoCodecType codec_type, + bool hw_codec, float packet_loss, int key_frame_interval, int num_temporal_layers, @@ -535,7 +599,7 @@ class VideoProcessorIntegrationTest : public testing::Test { bool denoising_on, bool frame_dropper_on, bool spatial_resize_on) { - SetCodecParameters(process_settings, codec_type, packet_loss, + SetCodecParameters(process_settings, codec_type, hw_codec, packet_loss, key_frame_interval, num_temporal_layers, error_concealment_on, denoising_on, frame_dropper_on, spatial_resize_on, kCifWidth, kCifHeight, @@ -575,7 +639,9 @@ class VideoProcessorIntegrationTest : public testing::Test { } std::unique_ptr encoder_; + std::unique_ptr external_encoder_factory_; std::unique_ptr decoder_; + std::unique_ptr external_decoder_factory_; std::unique_ptr frame_reader_; std::unique_ptr frame_writer_; test::PacketReader packet_reader_; @@ -583,6 +649,7 @@ class VideoProcessorIntegrationTest : public testing::Test { test::Stats stats_; test::TestConfig config_; VideoCodec codec_settings_; + // Must be destroyed before |encoder_| and |decoder_|. std::unique_ptr processor_; TemporalLayersFactory tl_factory_; @@ -612,6 +679,7 @@ class VideoProcessorIntegrationTest : public testing::Test { // Codec and network settings. VideoCodecType codec_type_; + bool hw_codec_; float packet_loss_; int num_temporal_layers_; int key_frame_interval_;