Skip to content

[camerax] Retrieve exposure and zoom camera information #3798

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

Merged
merged 23 commits into from
May 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions packages/camera/camera_android_camerax/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@
* Updates internal Java InstanceManager to only stop finalization callbacks when stopped.
* Implements image streaming.
* Provides LifecycleOwner implementation for Activities that use the plugin that do not implement it themselves.
* Implements retrieval of camera information.
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,10 @@ public void setUp(
// Set up Host APIs.
GeneratedCameraXLibrary.InstanceManagerHostApi.setup(
binaryMessenger, () -> instanceManager.clear());
GeneratedCameraXLibrary.CameraHostApi.setup(
binaryMessenger, new CameraHostApiImpl(binaryMessenger, instanceManager));
GeneratedCameraXLibrary.CameraInfoHostApi.setup(
binaryMessenger, new CameraInfoHostApiImpl(instanceManager));
binaryMessenger, new CameraInfoHostApiImpl(binaryMessenger, instanceManager));
GeneratedCameraXLibrary.CameraSelectorHostApi.setup(
binaryMessenger, new CameraSelectorHostApiImpl(binaryMessenger, instanceManager));
GeneratedCameraXLibrary.JavaObjectHostApi.setup(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package io.flutter.plugins.camerax;

import androidx.annotation.NonNull;
import androidx.camera.core.Camera;
import androidx.camera.core.CameraInfo;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.CameraHostApi;
import java.util.Objects;

public class CameraHostApiImpl implements CameraHostApi {
private final BinaryMessenger binaryMessenger;
private final InstanceManager instanceManager;

public CameraHostApiImpl(
@NonNull BinaryMessenger binaryMessenger, @NonNull InstanceManager instanceManager) {
this.binaryMessenger = binaryMessenger;
this.instanceManager = instanceManager;
}

/**
* Retrieves the {@link CameraInfo} instance that contains information about the {@link Camera}
* instance with the specified identifier.
*/
@Override
@NonNull
public Long getCameraInfo(@NonNull Long identifier) {
Camera camera = (Camera) Objects.requireNonNull(instanceManager.getInstance(identifier));
CameraInfo cameraInfo = camera.getCameraInfo();

CameraInfoFlutterApiImpl cameraInfoFlutterApiImpl =
new CameraInfoFlutterApiImpl(binaryMessenger, instanceManager);
cameraInfoFlutterApiImpl.create(cameraInfo, reply -> {});

return instanceManager.getIdentifierForStrongReference(cameraInfo);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public CameraInfoFlutterApiImpl(
}

void create(CameraInfo cameraInfo, Reply<Void> reply) {
create(instanceManager.addHostCreatedInstance(cameraInfo), reply);
if (!instanceManager.containsInstance(cameraInfo)) {
create(instanceManager.addHostCreatedInstance(cameraInfo), reply);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,64 @@

import androidx.annotation.NonNull;
import androidx.camera.core.CameraInfo;
import androidx.camera.core.ExposureState;
import androidx.camera.core.ZoomState;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.CameraInfoHostApi;
import java.util.Objects;

public class CameraInfoHostApiImpl implements CameraInfoHostApi {
private final BinaryMessenger binaryMessenger;
private final InstanceManager instanceManager;

public CameraInfoHostApiImpl(InstanceManager instanceManager) {
public CameraInfoHostApiImpl(
@NonNull BinaryMessenger binaryMessenger, @NonNull InstanceManager instanceManager) {
this.binaryMessenger = binaryMessenger;
this.instanceManager = instanceManager;
}

/** Retrieves the sensor rotation in degrees, relative to the device's default orientation. */
@Override
@NonNull
public Long getSensorRotationDegrees(@NonNull Long identifier) {
CameraInfo cameraInfo =
(CameraInfo) Objects.requireNonNull(instanceManager.getInstance(identifier));
return Long.valueOf(cameraInfo.getSensorRotationDegrees());
}

/**
* Retrieves the {@link ExposureState} of the {@link CameraInfo} with the specified identifier.
*/
@Override
@NonNull
public Long getExposureState(@NonNull Long identifier) {
CameraInfo cameraInfo =
(CameraInfo) Objects.requireNonNull(instanceManager.getInstance(identifier));
ExposureState exposureState = cameraInfo.getExposureState();

ExposureStateFlutterApiImpl exposureStateFlutterApiImpl =
new ExposureStateFlutterApiImpl(binaryMessenger, instanceManager);
exposureStateFlutterApiImpl.create(exposureState, result -> {});

return instanceManager.getIdentifierForStrongReference(exposureState);
}

/**
* Retrieves the current {@link ZoomState} value of the {@link CameraInfo} with the specified
* identifier.
*/
@NonNull
@Override
public Long getZoomState(@NonNull Long identifier) {
CameraInfo cameraInfo =
(CameraInfo) Objects.requireNonNull(instanceManager.getInstance(identifier));
// TODO(camsim99): Create/return LiveData<ZoomState> once https://github.com/flutter/packages/pull/3419 lands.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will fix this in that PR if this lands first if I have time. Otherwise, I'll file an issue and update this line in that PR.

ZoomState zoomState = cameraInfo.getZoomState().getValue();

ZoomStateFlutterApiImpl zoomStateFlutterApiImpl =
new ZoomStateFlutterApiImpl(binaryMessenger, instanceManager);
zoomStateFlutterApiImpl.create(zoomState, result -> {});

return instanceManager.getIdentifierForStrongReference(zoomState);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package io.flutter.plugins.camerax;

import android.util.Range;
import androidx.annotation.NonNull;
import androidx.camera.core.ExposureState;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.ExposureCompensationRange;
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.ExposureStateFlutterApi;

public class ExposureStateFlutterApiImpl extends ExposureStateFlutterApi {
private final InstanceManager instanceManager;

public ExposureStateFlutterApiImpl(
@NonNull BinaryMessenger binaryMessenger, @NonNull InstanceManager instanceManager) {
super(binaryMessenger);
this.instanceManager = instanceManager;
}

/**
* Creates a {@link ExposureState} on the Dart side with its exposure compensation range that can
* be used to set the exposure compensation index and its exposure compensation step, the smallest
* step by which the exposure compensation can be changed.
*/
void create(@NonNull ExposureState exposureState, @NonNull Reply<Void> reply) {
if (instanceManager.containsInstance(exposureState)) {
return;
}

final Range<Integer> exposureCompensationRangeFromState =
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this should block this PR, but I should move logic like this out of the create methods since they are constructor-adjacent.

exposureState.getExposureCompensationRange();
ExposureCompensationRange exposureCompensationRange =
new ExposureCompensationRange.Builder()
.setMinCompensation(exposureCompensationRangeFromState.getLower().longValue())
.setMaxCompensation(exposureCompensationRangeFromState.getUpper().longValue())
.build();
final Double exposureCompensationStep =
exposureState.getExposureCompensationStep().doubleValue();

create(
instanceManager.addHostCreatedInstance(exposureState),
exposureCompensationRange,
exposureCompensationStep,
reply);
}
}
Loading