From ce17e01bf6609a65e3efa5dac27daf13eee85c48 Mon Sep 17 00:00:00 2001 From: magjed Date: Wed, 1 Jun 2016 00:43:59 -0700 Subject: [PATCH] Reland of Android: Change camera fps range selection (patchset #1 id:1 of https://codereview.webrtc.org/2021233002/ ) Reason for revert: Fixed gyp bug. Original issue's description: > Revert of Android: Change camera fps range selection (patchset #4 id:100001 of https://codereview.webrtc.org/2013413002/ ) > > Reason for revert: > Breaks chromium fyi: > https://build.chromium.org/p/chromium.webrtc.fyi/builders/Mac%20Builder/builds/13565 > on step 'generate_build_files': > gyp: /b/build/slave/Mac_Builder/build/src/third_party/build/android/test_runner.gypi not found > > Original issue's description: > > Android: Change camera fps range selection > > > > This CL changes the logic in > > CameraEnumerationAndroid.getClosestSupportedFramerateRange() to prefer > > fps ranges with a low lower bound so the camera can adjust for > > brightness conditions. > > > > To test the functionality of the fps range selection, JUnit tests are > > added. This required a new target in api_tests.gyp. JUnit tests are > > preferable over instrumentation tests > > (libjingle_peerconnection_android_unittest) because they are faster and > > simpler. > > > > R=kjellander@webrtc.org, sakal@webrtc.org > > > > Committed: https://crrev.com/b4ddb5c3d3706b1c02437f6a538576f3552ab908 > > Cr-Commit-Position: refs/heads/master@{#12964} > > TBR=sakal@webrtc.org,kjellander@webrtc.org > # Skipping CQ checks because original CL landed less than 1 days ago. > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > > Committed: https://crrev.com/b3f208d0ba45f140272e3e705b5cdadc3c76514b > Cr-Commit-Position: refs/heads/master@{#12966} TBR=sakal@webrtc.org,kjellander@webrtc.org # Skipping CQ checks because original CL landed less than 1 days ago. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true Review-Url: https://codereview.webrtc.org/2028583002 Cr-Commit-Position: refs/heads/master@{#12980} --- webrtc/androidjunit/OWNERS | 2 + .../src/org/webrtc/CameraEnumerationTest.java | 55 +++++++++++++++++++ .../org/webrtc/CameraEnumerationAndroid.java | 26 ++++++++- webrtc/build/android_tests.gyp | 41 ++++++++++++-- webrtc/build/android_tests_noop.gyp | 4 ++ webrtc/webrtc_tests.gypi | 7 +++ 6 files changed, 128 insertions(+), 7 deletions(-) create mode 100644 webrtc/androidjunit/OWNERS create mode 100644 webrtc/androidjunit/src/org/webrtc/CameraEnumerationTest.java diff --git a/webrtc/androidjunit/OWNERS b/webrtc/androidjunit/OWNERS new file mode 100644 index 0000000000..299e8b20ec --- /dev/null +++ b/webrtc/androidjunit/OWNERS @@ -0,0 +1,2 @@ +magjed@webrtc.org +sakal@webrtc.org diff --git a/webrtc/androidjunit/src/org/webrtc/CameraEnumerationTest.java b/webrtc/androidjunit/src/org/webrtc/CameraEnumerationTest.java new file mode 100644 index 0000000000..b1ebb6c360 --- /dev/null +++ b/webrtc/androidjunit/src/org/webrtc/CameraEnumerationTest.java @@ -0,0 +1,55 @@ +/* + * Copyright 2016 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. + */ + +package org.webrtc; + +import static org.junit.Assert.assertEquals; +import static org.webrtc.CameraEnumerationAndroid.getClosestSupportedFramerateRange; + +import org.webrtc.CameraEnumerationAndroid.CaptureFormat; +import org.webrtc.CameraEnumerationAndroid.CaptureFormat.FramerateRange; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import java.util.Arrays; + +/** + * Tests for CameraEnumerationAndroid. + */ +@RunWith(RobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public class CameraEnumerationTest { + @Test + public void testGetClosestSupportedFramerateRange() { + assertEquals(new FramerateRange(10000, 30000), + getClosestSupportedFramerateRange( + Arrays.asList(new FramerateRange(10000, 30000), + new FramerateRange(30000, 30000)), + 30 /* requestedFps */)); + + assertEquals(new FramerateRange(10000, 20000), + getClosestSupportedFramerateRange( + Arrays.asList(new FramerateRange(0, 30000), + new FramerateRange(10000, 20000), + new FramerateRange(14000, 16000), + new FramerateRange(15000, 15000)), + 15 /* requestedFps */)); + + assertEquals(new FramerateRange(10000, 20000), + getClosestSupportedFramerateRange( + Arrays.asList(new FramerateRange(15000, 15000), + new FramerateRange(10000, 20000), + new FramerateRange(10000, 30000)), + 10 /* requestedFps */)); + } +} diff --git a/webrtc/api/java/android/org/webrtc/CameraEnumerationAndroid.java b/webrtc/api/java/android/org/webrtc/CameraEnumerationAndroid.java index 2fa685d1fb..87b9a40b62 100644 --- a/webrtc/api/java/android/org/webrtc/CameraEnumerationAndroid.java +++ b/webrtc/api/java/android/org/webrtc/CameraEnumerationAndroid.java @@ -181,15 +181,37 @@ public class CameraEnumerationAndroid { } } + // Prefer a fps range with an upper bound close to |framerate|. Also prefer a fps range with a low + // lower bound, to allow the framerate to fluctuate based on lightning conditions. public static CaptureFormat.FramerateRange getClosestSupportedFramerateRange( List supportedFramerates, final int requestedFps) { return Collections.min(supportedFramerates, new ClosestComparator() { - private static final int MAX_FPS_WEIGHT = 10; + // Progressive penalty if the upper bound is further away than |MAX_FPS_DIFF_THRESHOLD| + // from requested. + private static final int MAX_FPS_DIFF_THRESHOLD = 5000; + private static final int MAX_FPS_LOW_DIFF_WEIGHT = 1; + private static final int MAX_FPS_HIGH_DIFF_WEIGHT = 3; + + // Progressive penalty if the lower bound is bigger than |MIN_FPS_THRESHOLD|. + private static final int MIN_FPS_THRESHOLD = 8000; + private static final int MIN_FPS_LOW_VALUE_WEIGHT = 1; + private static final int MIN_FPS_HIGH_VALUE_WEIGHT = 4; + + // Use one weight for small |value| less than |threshold|, and another weight above. + private int progressivePenalty(int value, int threshold, int lowWeight, int highWeight) { + return (value < threshold) + ? value * lowWeight + : threshold * lowWeight + (value - threshold) * highWeight; + } @Override int diff(CaptureFormat.FramerateRange range) { - return range.min + MAX_FPS_WEIGHT * abs(requestedFps * 1000 - range.max); + final int minFpsError = progressivePenalty(range.min, + MIN_FPS_THRESHOLD, MIN_FPS_LOW_VALUE_WEIGHT, MIN_FPS_HIGH_VALUE_WEIGHT); + final int maxFpsError = progressivePenalty(Math.abs(requestedFps * 1000 - range.max), + MAX_FPS_DIFF_THRESHOLD, MAX_FPS_LOW_DIFF_WEIGHT, MAX_FPS_HIGH_DIFF_WEIGHT); + return minFpsError + maxFpsError; } }); } diff --git a/webrtc/build/android_tests.gyp b/webrtc/build/android_tests.gyp index 8bd2b97694..fdf72737a1 100644 --- a/webrtc/build/android_tests.gyp +++ b/webrtc/build/android_tests.gyp @@ -17,14 +17,12 @@ 'includes': [ 'common.gypi', ], - 'variables': { - 'shard_timeout': 900, - }, 'targets': [ { 'target_name': 'audio_codec_speed_tests_apk', 'type': 'none', 'variables': { + 'shard_timeout': 900, 'test_suite_name': 'audio_codec_speed_tests', 'input_shlib_path': '<(SHARED_LIB_DIR)/<(SHARED_LIB_PREFIX)audio_codec_speed_tests<(SHARED_LIB_SUFFIX)', 'isolate_file': '../modules/audio_codec_speed_tests.isolate', @@ -40,6 +38,7 @@ 'target_name': 'audio_decoder_unittests_apk', 'type': 'none', 'variables': { + 'shard_timeout': 900, 'test_suite_name': 'audio_decoder_unittests', 'input_shlib_path': '<(SHARED_LIB_DIR)/<(SHARED_LIB_PREFIX)audio_decoder_unittests<(SHARED_LIB_SUFFIX)', 'isolate_file': '../modules/audio_decoder_unittests.isolate', @@ -55,6 +54,7 @@ 'target_name': 'common_audio_unittests_apk', 'type': 'none', 'variables': { + 'shard_timeout': 900, 'test_suite_name': 'common_audio_unittests', 'input_shlib_path': '<(SHARED_LIB_DIR)/<(SHARED_LIB_PREFIX)common_audio_unittests<(SHARED_LIB_SUFFIX)', 'isolate_file': '../common_audio/common_audio_unittests.isolate', @@ -70,6 +70,7 @@ 'target_name': 'common_video_unittests_apk', 'type': 'none', 'variables': { + 'shard_timeout': 900, 'test_suite_name': 'common_video_unittests', 'input_shlib_path': '<(SHARED_LIB_DIR)/<(SHARED_LIB_PREFIX)common_video_unittests<(SHARED_LIB_SUFFIX)', 'isolate_file': '../common_video/common_video_unittests.isolate', @@ -85,6 +86,7 @@ 'target_name': 'modules_tests_apk', 'type': 'none', 'variables': { + 'shard_timeout': 900, 'test_suite_name': 'modules_tests', 'input_shlib_path': '<(SHARED_LIB_DIR)/<(SHARED_LIB_PREFIX)modules_tests<(SHARED_LIB_SUFFIX)', 'isolate_file': '../modules/modules_tests.isolate', @@ -100,6 +102,7 @@ 'target_name': 'modules_unittests_apk', 'type': 'none', 'variables': { + 'shard_timeout': 900, 'test_suite_name': 'modules_unittests', 'input_shlib_path': '<(SHARED_LIB_DIR)/<(SHARED_LIB_PREFIX)modules_unittests<(SHARED_LIB_SUFFIX)', 'isolate_file': '../modules/modules_unittests.isolate', @@ -116,6 +119,7 @@ 'target_name': 'peerconnection_unittests_apk', 'type': 'none', 'variables': { + 'shard_timeout': 900, 'test_suite_name': 'peerconnection_unittests', 'input_shlib_path': '<(SHARED_LIB_DIR)/<(SHARED_LIB_PREFIX)peerconnection_unittests<(SHARED_LIB_SUFFIX)', 'isolate_file': '../api/peerconnection_unittests.isolate', @@ -132,6 +136,7 @@ 'target_name': 'rtc_unittests_apk', 'type': 'none', 'variables': { + 'shard_timeout': 900, 'test_suite_name': 'rtc_unittests', 'input_shlib_path': '<(SHARED_LIB_DIR)/<(SHARED_LIB_PREFIX)rtc_unittests<(SHARED_LIB_SUFFIX)', 'isolate_file': '../rtc_unittests.isolate', @@ -147,6 +152,7 @@ 'target_name': 'system_wrappers_unittests_apk', 'type': 'none', 'variables': { + 'shard_timeout': 900, 'test_suite_name': 'system_wrappers_unittests', 'input_shlib_path': '<(SHARED_LIB_DIR)/<(SHARED_LIB_PREFIX)system_wrappers_unittests<(SHARED_LIB_SUFFIX)', 'isolate_file': '../system_wrappers/system_wrappers_unittests.isolate', @@ -162,6 +168,7 @@ 'target_name': 'test_support_unittests_apk', 'type': 'none', 'variables': { + 'shard_timeout': 900, 'test_suite_name': 'test_support_unittests', 'input_shlib_path': '<(SHARED_LIB_DIR)/<(SHARED_LIB_PREFIX)test_support_unittests<(SHARED_LIB_SUFFIX)', 'isolate_file': '../test/test_support_unittests.isolate', @@ -177,6 +184,7 @@ 'target_name': 'tools_unittests_apk', 'type': 'none', 'variables': { + 'shard_timeout': 900, 'test_suite_name': 'tools_unittests', 'input_shlib_path': '<(SHARED_LIB_DIR)/<(SHARED_LIB_PREFIX)tools_unittests<(SHARED_LIB_SUFFIX)', 'isolate_file': '../tools/tools_unittests.isolate', @@ -192,6 +200,7 @@ 'target_name': 'video_engine_tests_apk', 'type': 'none', 'variables': { + 'shard_timeout': 900, 'test_suite_name': 'video_engine_tests', 'input_shlib_path': '<(SHARED_LIB_DIR)/<(SHARED_LIB_PREFIX)video_engine_tests<(SHARED_LIB_SUFFIX)', 'isolate_file': '../video_engine_tests.isolate', @@ -207,6 +216,7 @@ 'target_name': 'voice_engine_unittests_apk', 'type': 'none', 'variables': { + 'shard_timeout': 900, 'test_suite_name': 'voice_engine_unittests', 'input_shlib_path': '<(SHARED_LIB_DIR)/<(SHARED_LIB_PREFIX)voice_engine_unittests<(SHARED_LIB_SUFFIX)', 'isolate_file': '../voice_engine/voice_engine_unittests.isolate', @@ -238,6 +248,7 @@ 'target_name': 'webrtc_nonparallel_tests_apk', 'type': 'none', 'variables': { + 'shard_timeout': 900, 'test_suite_name': 'webrtc_nonparallel_tests', 'input_shlib_path': '<(SHARED_LIB_DIR)/<(SHARED_LIB_PREFIX)webrtc_nonparallel_tests<(SHARED_LIB_SUFFIX)', 'isolate_file': '../webrtc_nonparallel_tests.isolate', @@ -249,6 +260,28 @@ '../../build/apk_test.gypi', ], }, + { + 'target_name': 'android_junit_tests', + 'type': 'none', + 'dependencies': [ + '<(webrtc_root)/api/api.gyp:libjingle_peerconnection_java', + '<(DEPTH)/base/base.gyp:base_java', + '<(DEPTH)/base/base.gyp:base_java_test_support', + '<(DEPTH)/base/base.gyp:base_junit_test_support', + ], + 'variables': { + 'main_class': 'org.chromium.testing.local.JunitTestMain', + 'src_paths': [ + '../androidjunit/', + ], + 'test_type': 'junit', + 'wrapper_script_name': 'helper/<(_target_name)', + }, + 'includes': [ + '../../build/android/test_runner.gypi', + '../../build/host_jar.gypi', + ], + }, { 'target_name': 'audio_device_java', 'type': 'none', @@ -263,5 +296,3 @@ }, ], } - - diff --git a/webrtc/build/android_tests_noop.gyp b/webrtc/build/android_tests_noop.gyp index 441f50750e..fd6835b9af 100644 --- a/webrtc/build/android_tests_noop.gyp +++ b/webrtc/build/android_tests_noop.gyp @@ -69,5 +69,9 @@ 'target_name': 'audio_codec_speed_tests_apk', 'type': 'none', }, + { + 'target_name': 'android_junit_tests', + 'type': 'none', + }, ], } diff --git a/webrtc/webrtc_tests.gypi b/webrtc/webrtc_tests.gypi index 0c7dff2f5e..afd34a4f62 100644 --- a/webrtc/webrtc_tests.gypi +++ b/webrtc/webrtc_tests.gypi @@ -353,6 +353,13 @@ '<(android_tests_path):webrtc_nonparallel_tests_apk', ], }, + { + 'target_name': 'android_junit_tests_target', + 'type': 'none', + 'dependencies': [ + '<(android_tests_path):android_junit_tests', + ], + }, ], 'conditions': [ ['test_isolation_mode != "noop"',