Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Commit d91b008

Browse files
authored
[camera] android-rework part 7: Android noise reduction feature (#4052)
1 parent 0232846 commit d91b008

File tree

4 files changed

+295
-0
lines changed

4 files changed

+295
-0
lines changed

packages/camera/camera/android/src/main/java/io/flutter/plugins/camera/features/flash/FlashMode.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@ public enum FlashMode {
1717
this.strValue = strValue;
1818
}
1919

20+
/**
21+
* Tries to convert the supplied string into a {@see FlashMode} enum value.
22+
*
23+
* <p>When the supplied string doesn't match a valid {@see FlashMode} enum value, null is
24+
* returned.
25+
*
26+
* @param modeStr String value to convert into an {@see FlashMode} enum value.
27+
* @return Matching {@see FlashMode} enum value, or null if no match is found.
28+
*/
2029
public static FlashMode getValueForString(String modeStr) {
2130
for (FlashMode value : values()) {
2231
if (value.strValue.equals(modeStr)) return value;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
package io.flutter.plugins.camera.features.noisereduction;
6+
7+
import android.hardware.camera2.CaptureRequest;
8+
import android.os.Build.VERSION;
9+
import android.os.Build.VERSION_CODES;
10+
import android.util.Log;
11+
import io.flutter.plugins.camera.CameraProperties;
12+
import io.flutter.plugins.camera.features.CameraFeature;
13+
import java.util.HashMap;
14+
15+
/**
16+
* This can either be enabled or disabled. Only full capability devices can set this to off. Legacy
17+
* and full support the fast mode.
18+
* https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES
19+
*/
20+
public class NoiseReductionFeature extends CameraFeature<NoiseReductionMode> {
21+
private NoiseReductionMode currentSetting = NoiseReductionMode.fast;
22+
23+
private static final HashMap<NoiseReductionMode, Integer> NOISE_REDUCTION_MODES = new HashMap<>();
24+
25+
static {
26+
NOISE_REDUCTION_MODES.put(NoiseReductionMode.off, CaptureRequest.NOISE_REDUCTION_MODE_OFF);
27+
NOISE_REDUCTION_MODES.put(NoiseReductionMode.fast, CaptureRequest.NOISE_REDUCTION_MODE_FAST);
28+
NOISE_REDUCTION_MODES.put(
29+
NoiseReductionMode.highQuality, CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY);
30+
if (VERSION.SDK_INT >= VERSION_CODES.M) {
31+
NOISE_REDUCTION_MODES.put(
32+
NoiseReductionMode.minimal, CaptureRequest.NOISE_REDUCTION_MODE_MINIMAL);
33+
NOISE_REDUCTION_MODES.put(
34+
NoiseReductionMode.zeroShutterLag, CaptureRequest.NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG);
35+
}
36+
}
37+
38+
/**
39+
* Creates a new instance of the {@link NoiseReductionFeature}.
40+
*
41+
* @param cameraProperties Collection of the characteristics for the current camera device.
42+
*/
43+
public NoiseReductionFeature(CameraProperties cameraProperties) {
44+
super(cameraProperties);
45+
}
46+
47+
@Override
48+
public String getDebugName() {
49+
return "NoiseReductionFeature";
50+
}
51+
52+
@Override
53+
public NoiseReductionMode getValue() {
54+
return currentSetting;
55+
}
56+
57+
@Override
58+
public void setValue(NoiseReductionMode value) {
59+
this.currentSetting = value;
60+
}
61+
62+
@Override
63+
public boolean checkIsSupported() {
64+
/*
65+
* Available settings: public static final int NOISE_REDUCTION_MODE_FAST = 1; public static
66+
* final int NOISE_REDUCTION_MODE_HIGH_QUALITY = 2; public static final int
67+
* NOISE_REDUCTION_MODE_MINIMAL = 3; public static final int NOISE_REDUCTION_MODE_OFF = 0;
68+
* public static final int NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG = 4;
69+
*
70+
* <p>Full-capability camera devices will always support OFF and FAST. Camera devices that
71+
* support YUV_REPROCESSING or PRIVATE_REPROCESSING will support ZERO_SHUTTER_LAG.
72+
* Legacy-capability camera devices will only support FAST mode.
73+
*/
74+
75+
// Can be null on some devices.
76+
int[] modes = cameraProperties.getAvailableNoiseReductionModes();
77+
78+
/// If there's at least one mode available then we are supported.
79+
return modes != null && modes.length > 0;
80+
}
81+
82+
@Override
83+
public void updateBuilder(CaptureRequest.Builder requestBuilder) {
84+
if (!checkIsSupported()) {
85+
return;
86+
}
87+
88+
Log.i("Camera", "updateNoiseReduction | currentSetting: " + currentSetting);
89+
90+
// Always use fast mode.
91+
requestBuilder.set(
92+
CaptureRequest.NOISE_REDUCTION_MODE, NOISE_REDUCTION_MODES.get(currentSetting));
93+
}
94+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
package io.flutter.plugins.camera.features.noisereduction;
6+
7+
/** Only supports fast mode for now. */
8+
public enum NoiseReductionMode {
9+
off("off"),
10+
fast("fast"),
11+
highQuality("highQuality"),
12+
minimal("minimal"),
13+
zeroShutterLag("zeroShutterLag");
14+
15+
private final String strValue;
16+
17+
NoiseReductionMode(String strValue) {
18+
this.strValue = strValue;
19+
}
20+
21+
/**
22+
* Tries to convert the supplied string into a {@see NoiseReductionMode} enum value.
23+
*
24+
* <p>When the supplied string doesn't match a valid {@see NoiseReductionMode} enum value, null is
25+
* returned.
26+
*
27+
* @param modeStr String value to convert into an {@see NoiseReductionMode} enum value.
28+
* @return Matching {@see NoiseReductionMode} enum value, or null if no match is found.
29+
*/
30+
public static NoiseReductionMode getValueForString(String modeStr) {
31+
for (NoiseReductionMode value : values()) {
32+
if (value.strValue.equals(modeStr)) return value;
33+
}
34+
return null;
35+
}
36+
37+
@Override
38+
public String toString() {
39+
return strValue;
40+
}
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
package io.flutter.plugins.camera.features.noisereduction;
6+
7+
import static org.junit.Assert.assertEquals;
8+
import static org.junit.Assert.assertFalse;
9+
import static org.junit.Assert.assertTrue;
10+
import static org.mockito.ArgumentMatchers.any;
11+
import static org.mockito.Mockito.mock;
12+
import static org.mockito.Mockito.never;
13+
import static org.mockito.Mockito.times;
14+
import static org.mockito.Mockito.verify;
15+
import static org.mockito.Mockito.when;
16+
17+
import android.hardware.camera2.CaptureRequest;
18+
import android.os.Build.VERSION;
19+
import io.flutter.plugins.camera.CameraProperties;
20+
import io.flutter.plugins.camera.utils.TestUtils;
21+
import org.junit.After;
22+
import org.junit.Before;
23+
import org.junit.Test;
24+
25+
public class NoiseReductionFeatureTest {
26+
@Before
27+
public void before() {
28+
// Make sure the VERSION.SDK_INT field returns 23, to allow using all available
29+
// noise reduction modes in tests.
30+
TestUtils.setFinalStatic(VERSION.class, "SDK_INT", 23);
31+
}
32+
33+
@After
34+
public void after() {
35+
// Make sure we reset the VERSION.SDK_INT field to it's original value.
36+
TestUtils.setFinalStatic(VERSION.class, "SDK_INT", 0);
37+
}
38+
39+
@Test
40+
public void getDebugName_should_return_the_name_of_the_feature() {
41+
CameraProperties mockCameraProperties = mock(CameraProperties.class);
42+
NoiseReductionFeature noiseReductionFeature = new NoiseReductionFeature(mockCameraProperties);
43+
44+
assertEquals("NoiseReductionFeature", noiseReductionFeature.getDebugName());
45+
}
46+
47+
@Test
48+
public void getValue_should_return_fast_if_not_set() {
49+
CameraProperties mockCameraProperties = mock(CameraProperties.class);
50+
NoiseReductionFeature noiseReductionFeature = new NoiseReductionFeature(mockCameraProperties);
51+
52+
assertEquals(NoiseReductionMode.fast, noiseReductionFeature.getValue());
53+
}
54+
55+
@Test
56+
public void getValue_should_echo_the_set_value() {
57+
CameraProperties mockCameraProperties = mock(CameraProperties.class);
58+
NoiseReductionFeature noiseReductionFeature = new NoiseReductionFeature(mockCameraProperties);
59+
NoiseReductionMode expectedValue = NoiseReductionMode.fast;
60+
61+
noiseReductionFeature.setValue(expectedValue);
62+
NoiseReductionMode actualValue = noiseReductionFeature.getValue();
63+
64+
assertEquals(expectedValue, actualValue);
65+
}
66+
67+
@Test
68+
public void checkIsSupported_should_return_false_when_available_noise_reduction_modes_is_null() {
69+
CameraProperties mockCameraProperties = mock(CameraProperties.class);
70+
NoiseReductionFeature noiseReductionFeature = new NoiseReductionFeature(mockCameraProperties);
71+
72+
when(mockCameraProperties.getAvailableNoiseReductionModes()).thenReturn(null);
73+
74+
assertFalse(noiseReductionFeature.checkIsSupported());
75+
}
76+
77+
@Test
78+
public void
79+
checkIsSupported_should_return_false_when_available_noise_reduction_modes_returns_an_empty_array() {
80+
CameraProperties mockCameraProperties = mock(CameraProperties.class);
81+
NoiseReductionFeature noiseReductionFeature = new NoiseReductionFeature(mockCameraProperties);
82+
83+
when(mockCameraProperties.getAvailableNoiseReductionModes()).thenReturn(new int[] {});
84+
85+
assertFalse(noiseReductionFeature.checkIsSupported());
86+
}
87+
88+
@Test
89+
public void
90+
checkIsSupported_should_return_true_when_available_noise_reduction_modes_returns_at_least_one_item() {
91+
CameraProperties mockCameraProperties = mock(CameraProperties.class);
92+
NoiseReductionFeature noiseReductionFeature = new NoiseReductionFeature(mockCameraProperties);
93+
94+
when(mockCameraProperties.getAvailableNoiseReductionModes()).thenReturn(new int[] {1});
95+
96+
assertTrue(noiseReductionFeature.checkIsSupported());
97+
}
98+
99+
@Test
100+
public void updateBuilder_should_return_when_checkIsSupported_is_false() {
101+
CameraProperties mockCameraProperties = mock(CameraProperties.class);
102+
CaptureRequest.Builder mockBuilder = mock(CaptureRequest.Builder.class);
103+
NoiseReductionFeature noiseReductionFeature = new NoiseReductionFeature(mockCameraProperties);
104+
105+
when(mockCameraProperties.getAvailableNoiseReductionModes()).thenReturn(new int[] {});
106+
107+
noiseReductionFeature.updateBuilder(mockBuilder);
108+
109+
verify(mockBuilder, never()).set(any(), any());
110+
}
111+
112+
@Test
113+
public void updateBuilder_should_set_noise_reduction_mode_off_when_off() {
114+
testUpdateBuilderWith(NoiseReductionMode.off, CaptureRequest.NOISE_REDUCTION_MODE_OFF);
115+
}
116+
117+
@Test
118+
public void updateBuilder_should_set_noise_reduction_mode_fast_when_fast() {
119+
testUpdateBuilderWith(NoiseReductionMode.fast, CaptureRequest.NOISE_REDUCTION_MODE_FAST);
120+
}
121+
122+
@Test
123+
public void updateBuilder_should_set_noise_reduction_mode_high_quality_when_high_quality() {
124+
testUpdateBuilderWith(
125+
NoiseReductionMode.highQuality, CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY);
126+
}
127+
128+
@Test
129+
public void updateBuilder_should_set_noise_reduction_mode_minimal_when_minimal() {
130+
testUpdateBuilderWith(NoiseReductionMode.minimal, CaptureRequest.NOISE_REDUCTION_MODE_MINIMAL);
131+
}
132+
133+
@Test
134+
public void
135+
updateBuilder_should_set_noise_reduction_mode_zero_shutter_lag_when_zero_shutter_lag() {
136+
testUpdateBuilderWith(
137+
NoiseReductionMode.zeroShutterLag, CaptureRequest.NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG);
138+
}
139+
140+
private static void testUpdateBuilderWith(NoiseReductionMode mode, int expectedResult) {
141+
CameraProperties mockCameraProperties = mock(CameraProperties.class);
142+
CaptureRequest.Builder mockBuilder = mock(CaptureRequest.Builder.class);
143+
NoiseReductionFeature noiseReductionFeature = new NoiseReductionFeature(mockCameraProperties);
144+
145+
when(mockCameraProperties.getAvailableNoiseReductionModes()).thenReturn(new int[] {1});
146+
147+
noiseReductionFeature.setValue(mode);
148+
noiseReductionFeature.updateBuilder(mockBuilder);
149+
verify(mockBuilder, times(1)).set(CaptureRequest.NOISE_REDUCTION_MODE, expectedResult);
150+
}
151+
}

0 commit comments

Comments
 (0)