Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[camerax] Implements setFocusMode #6176

Merged
merged 32 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
b915f7d
Locked hacking
camsim99 Feb 20, 2024
0b33c78
This works but may need to swap in/out af points. I will see
camsim99 Feb 21, 2024
03b2095
Merge remote-tracking branch 'upstream/main' into camx_fmode
camsim99 Feb 21, 2024
f1bdb1f
Formatting
camsim99 Feb 21, 2024
bd1f1ba
Undo incorrect test changes
camsim99 Feb 21, 2024
24dd03b
Undo more changes
camsim99 Feb 21, 2024
f73c2fb
Add disableAutoCancel param + leave todos for case handling
camsim99 Feb 21, 2024
d4d1588
Formatting
camsim99 Feb 21, 2024
dd4f6b3
Add case logic
camsim99 Feb 22, 2024
b902c04
Add todo for AWB
camsim99 Feb 22, 2024
81a5170
Merge remote-tracking branch 'upstream/main' into camx_fmode
camsim99 Feb 22, 2024
72d2d5f
Manual testing
camsim99 Feb 26, 2024
32118bc
Self review
camsim99 Feb 26, 2024
da114ab
Start adding tests
camsim99 Feb 27, 2024
2965929
Add more tests
camsim99 Feb 27, 2024
861ae64
Adding more tests
camsim99 Feb 27, 2024
211962d
Merge remote-tracking branch 'upstream/main' into camx_fmode
camsim99 Feb 27, 2024
23d23ed
Finish adding tests
camsim99 Feb 27, 2024
49392ae
Self review 2
camsim99 Feb 27, 2024
faa61c5
Java fixes
camsim99 Feb 27, 2024
d025a79
Nits
camsim99 Feb 27, 2024
f8d1a6d
Add scott warning
camsim99 Feb 27, 2024
d4b4998
Merge remote-tracking branch 'upstream/main' into camx_fmode
camsim99 Feb 27, 2024
7b2fb39
Address part of review + bump version to 0.6.0
camsim99 Mar 6, 2024
7ff3bc6
Use results
camsim99 Mar 8, 2024
81d0453
Add todo fix resetting mode
camsim99 Mar 11, 2024
1ec2045
Final fixes
camsim99 Mar 11, 2024
92123c3
Fix tests
camsim99 Mar 11, 2024
94622d0
Merge remote-tracking branch 'upstream/main' into camx_fmode
camsim99 Mar 11, 2024
b3d72cb
Add additional tests
camsim99 Mar 11, 2024
54e8fd3
Avoid breaking readme
camsim99 Mar 18, 2024
9568190
Update packages/camera/camera_android_camerax/CHANGELOG.md
camsim99 Mar 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/camera/camera_android_camerax/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.6.0

* Implements `setFocusMode`, which makes plugin reach feature parity with camera_android.
camsim99 marked this conversation as resolved.
Show resolved Hide resolved
* Fixes `setExposureCompensationIndex` return value to use index returned by CameraX.

## 0.5.0+36

* Implements `setExposureMode`.
Expand Down
8 changes: 2 additions & 6 deletions packages/camera/camera_android_camerax/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
An Android implementation of [`camera`][1] that uses the [CameraX library][2].

*Note*: This package is under development, so please note the
[missing features and limitations](#missing-features-and-limitations), but
[missing features and limitations](#limitations), but
otherwise feel free to try out the current implementation and provide any
feedback by filing issues under [`flutter/flutter`][5] with `[camerax]` in
the title, which will be actively triaged.
Expand All @@ -22,18 +22,14 @@ dependencies:
camera_android_camerax: ^0.5.0
```

## Missing features and limitations
## Limitations

### 240p resolution configuration for video recording

240p resolution configuration for video recording is unsupported by CameraX,
and thus, the plugin will fall back to 480p if configured with a
`ResolutionPreset`.

### Focus mode configuration \[[Issue #120467][120467]\]

`setFocusMode` is unimplemented.

### Setting maximum duration and stream options for video capture

Calling `startVideoCapturing` with `VideoCaptureOptions` configured with
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package io.flutter.plugins.camerax;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.camera.core.FocusMeteringAction;
import androidx.camera.core.MeteringPoint;
Expand All @@ -29,7 +30,9 @@ public class FocusMeteringActionHostApiImpl implements FocusMeteringActionHostAp
public static class FocusMeteringActionProxy {
/** Creates an instance of {@link FocusMeteringAction}. */
public @NonNull FocusMeteringAction create(
@NonNull List<MeteringPoint> meteringPoints, @NonNull List<Integer> meteringPointModes) {
@NonNull List<MeteringPoint> meteringPoints,
@NonNull List<Integer> meteringPointModes,
@Nullable Boolean disableAutoCancel) {
if (meteringPoints.size() >= 1 && meteringPoints.size() != meteringPointModes.size()) {
throw new IllegalArgumentException(
"One metering point must be specified and the number of specified metering points must match the number of specified metering point modes.");
Expand Down Expand Up @@ -59,6 +62,10 @@ public static class FocusMeteringActionProxy {
}
}

if (disableAutoCancel != null && disableAutoCancel == true) {
focusMeteringActionBuilder.disableAutoCancel();
}

return focusMeteringActionBuilder.build();
}

Expand Down Expand Up @@ -100,7 +107,9 @@ public FocusMeteringActionHostApiImpl(@NonNull InstanceManager instanceManager)

@Override
public void create(
@NonNull Long identifier, @NonNull List<MeteringPointInfo> meteringPointInfos) {
@NonNull Long identifier,
@NonNull List<MeteringPointInfo> meteringPointInfos,
@Nullable Boolean disableAutoCancel) {
final List<MeteringPoint> meteringPoints = new ArrayList<MeteringPoint>();
final List<Integer> meteringPointModes = new ArrayList<Integer>();
for (MeteringPointInfo meteringPointInfo : meteringPointInfos) {
Expand All @@ -110,6 +119,6 @@ public void create(
}

instanceManager.addDartCreatedInstance(
proxy.create(meteringPoints, meteringPointModes), identifier);
proxy.create(meteringPoints, meteringPointModes, disableAutoCancel), identifier);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3796,7 +3796,10 @@ protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) {
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
public interface FocusMeteringActionHostApi {

void create(@NonNull Long identifier, @NonNull List<MeteringPointInfo> meteringPointInfos);
void create(
@NonNull Long identifier,
@NonNull List<MeteringPointInfo> meteringPointInfos,
@Nullable Boolean disableAutoCancel);

/** The codec used by FocusMeteringActionHostApi. */
static @NonNull MessageCodec<Object> getCodec() {
Expand All @@ -3822,10 +3825,12 @@ static void setup(
Number identifierArg = (Number) args.get(0);
List<MeteringPointInfo> meteringPointInfosArg =
(List<MeteringPointInfo>) args.get(1);
Boolean disableAutoCancelArg = (Boolean) args.get(2);
try {
api.create(
(identifierArg == null) ? null : identifierArg.longValue(),
meteringPointInfosArg);
meteringPointInfosArg,
disableAutoCancelArg);
wrapped.add(0, null);
} catch (Throwable exception) {
ArrayList<Object> wrappedError = wrapError(exception);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
Expand Down Expand Up @@ -43,7 +44,7 @@ public void tearDown() {
}

@Test
public void hostApiCreatecreatesExpectedFocusMeteringActionWithInitialPointThatHasMode() {
public void hostApiCreate_createsExpectedFocusMeteringActionWithInitialPointThatHasMode() {
FocusMeteringActionHostApiImpl.FocusMeteringActionProxy proxySpy =
spy(new FocusMeteringActionHostApiImpl.FocusMeteringActionProxy());
FocusMeteringActionHostApiImpl hostApi =
Expand Down Expand Up @@ -89,7 +90,7 @@ public void hostApiCreatecreatesExpectedFocusMeteringActionWithInitialPointThatH
List<MeteringPointInfo> mockMeteringPointInfos =
Arrays.asList(fakeMeteringPointInfo1, fakeMeteringPointInfo2, fakeMeteringPointInfo3);

hostApi.create(focusMeteringActionIdentifier, mockMeteringPointInfos);
hostApi.create(focusMeteringActionIdentifier, mockMeteringPointInfos, null);

verify(mockFocusMeteringActionBuilder).addPoint(mockMeteringPoint2, mockMeteringPoint2Mode);
verify(mockFocusMeteringActionBuilder).addPoint(mockMeteringPoint3);
Expand All @@ -98,7 +99,8 @@ public void hostApiCreatecreatesExpectedFocusMeteringActionWithInitialPointThatH
}

@Test
public void hostApiCreatecreatesExpectedFocusMeteringActionWithInitialPointThatDoesNotHaveMode() {
public void
hostApiCreate_createsExpectedFocusMeteringActionWithInitialPointThatDoesNotHaveMode() {
FocusMeteringActionHostApiImpl.FocusMeteringActionProxy proxySpy =
spy(new FocusMeteringActionHostApiImpl.FocusMeteringActionProxy());
FocusMeteringActionHostApiImpl hostApi =
Expand Down Expand Up @@ -142,11 +144,49 @@ public void hostApiCreatecreatesExpectedFocusMeteringActionWithInitialPointThatD
List<MeteringPointInfo> mockMeteringPointInfos =
Arrays.asList(fakeMeteringPointInfo1, fakeMeteringPointInfo2, fakeMeteringPointInfo3);

hostApi.create(focusMeteringActionIdentifier, mockMeteringPointInfos);
hostApi.create(focusMeteringActionIdentifier, mockMeteringPointInfos, null);

verify(mockFocusMeteringActionBuilder).addPoint(mockMeteringPoint2, mockMeteringPoint2Mode);
verify(mockFocusMeteringActionBuilder).addPoint(mockMeteringPoint3);
assertEquals(
testInstanceManager.getInstance(focusMeteringActionIdentifier), focusMeteringAction);
}

@Test
public void hostApiCreate_disablesAutoCancelAsExpected() {
FocusMeteringActionHostApiImpl.FocusMeteringActionProxy proxySpy =
spy(new FocusMeteringActionHostApiImpl.FocusMeteringActionProxy());
FocusMeteringActionHostApiImpl hostApi =
new FocusMeteringActionHostApiImpl(testInstanceManager, proxySpy);

FocusMeteringAction.Builder mockFocusMeteringActionBuilder =
mock(FocusMeteringAction.Builder.class);
final MeteringPoint mockMeteringPoint = mock(MeteringPoint.class);
final Long mockMeteringPointId = 47L;

MeteringPointInfo fakeMeteringPointInfo =
new MeteringPointInfo.Builder()
.setMeteringPointId(mockMeteringPointId)
.setMeteringMode(null)
.build();

testInstanceManager.addDartCreatedInstance(mockMeteringPoint, mockMeteringPointId);

when(proxySpy.getFocusMeteringActionBuilder(mockMeteringPoint))
.thenReturn(mockFocusMeteringActionBuilder);
when(mockFocusMeteringActionBuilder.build()).thenReturn(focusMeteringAction);

List<MeteringPointInfo> mockMeteringPointInfos = Arrays.asList(fakeMeteringPointInfo);

// Test not disabling auto cancel.
hostApi.create(73L, mockMeteringPointInfos, /* disableAutoCancel */ null);
verify(mockFocusMeteringActionBuilder, never()).disableAutoCancel();

hostApi.create(74L, mockMeteringPointInfos, /* disableAutoCancel */ false);
verify(mockFocusMeteringActionBuilder, never()).disableAutoCancel();

// Test disabling auto cancel.
hostApi.create(75L, mockMeteringPointInfos, /* disableAutoCancel */ true);
verify(mockFocusMeteringActionBuilder).disableAutoCancel();
}
}
10 changes: 6 additions & 4 deletions packages/camera/camera_android_camerax/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -477,8 +477,9 @@ class _CameraExampleHomeState extends State<CameraExampleHome>
children: <Widget>[
TextButton(
style: styleAuto,
onPressed:
() {}, // TODO(camsim99): Add functionality back here.
onPressed: controller != null
? () => onSetFocusModeButtonPressed(FocusMode.auto)
: null,
onLongPress: () {
if (controller != null) {
CameraPlatform.instance
Expand All @@ -490,8 +491,9 @@ class _CameraExampleHomeState extends State<CameraExampleHome>
),
TextButton(
style: styleLocked,
onPressed:
() {}, // TODO(camsim99): Add functionality back here.
onPressed: controller != null
? () => onSetFocusModeButtonPressed(FocusMode.locked)
: null,
child: const Text('LOCKED'),
),
],
Expand Down
Loading