Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
2b7aa9b
Base classes to support Android camera features
mvanbeusekom Apr 8, 2021
f780742
Fixed formatting
mvanbeusekom Apr 8, 2021
76bc5bd
Applied feedback from PR
mvanbeusekom Apr 20, 2021
0bbed99
Added Android FPS range, resolution and sensor orientation features
mvanbeusekom Apr 8, 2021
1ba738d
Use mockito-inline
mvanbeusekom Apr 9, 2021
de4e70f
Merge remote-tracking branch 'upstream/master' into camera-android/fp…
mvanbeusekom Apr 21, 2021
728346a
Fix issue Pixel 4A
mvanbeusekom May 26, 2021
c014fe3
Merge remote-tracking branch 'upstream/master' into camera-android/fp…
mvanbeusekom May 31, 2021
84f5e73
Added API documentation
mvanbeusekom May 31, 2021
f763f77
Processed feedback on PR
mvanbeusekom May 31, 2021
4a7c73a
Fix formatting
mvanbeusekom May 31, 2021
a890919
Fix formatting
mvanbeusekom May 31, 2021
f60a0d3
Merge remote-tracking branch 'upstream/master'
BeMacized Jun 8, 2021
55a6702
Only exclude 60 FPS limit for Pixel 4a
mvanbeusekom Jun 8, 2021
cd53321
Removed redundant empty line
mvanbeusekom Jun 8, 2021
35831d3
Fixed comment
mvanbeusekom Jun 8, 2021
a9f3142
Test Pixel 4a workaround
mvanbeusekom Jun 8, 2021
551800e
Add tests for orientation updates
mvanbeusekom Jun 10, 2021
68cbc56
Fix formatting
mvanbeusekom Jun 10, 2021
1b137c2
Fix formatting
mvanbeusekom Jun 10, 2021
6514a00
Added missing license header
mvanbeusekom Jun 10, 2021
baae5f6
Add feature classes for exposure- and focus point functionality.
BeMacized Jun 10, 2021
cae8a90
Merge remote-tracking branch 'upstream/master'
BeMacized Jun 11, 2021
94fed08
Added noise reduction feature
BeMacized Jun 14, 2021
be05e67
Merge branch 'camera-android/noise_reduction_feature' into camera-and…
BeMacized Jun 14, 2021
a68b9fb
Merge branch 'camera-android/exposure_focus_point_features' into came…
BeMacized Jun 14, 2021
e5253c1
Merge remote-tracking branch 'origin/camera-android/fps_resolution_se…
BeMacized Jun 14, 2021
4f169ab
Implemented PR feedback
BeMacized Jun 15, 2021
3a68294
Implemented PR feedback
BeMacized Jun 15, 2021
70dbbd5
Add supporting functionality for android refactor
BeMacized Jun 15, 2021
8e65f33
Merge branch 'camera-android/exposure_focus_point_features' into came…
BeMacized Jun 16, 2021
2c64ea2
Merge branch 'camera-android/noise_reduction_feature' into camera-and…
BeMacized Jun 16, 2021
ab332ee
Update packages/camera/camera/android/src/main/java/io/flutter/plugin…
BeMacized Jun 16, 2021
bc16dd3
Update packages/camera/camera/android/src/main/java/io/flutter/plugin…
BeMacized Jun 16, 2021
a85e312
Update packages/camera/camera/android/src/main/java/io/flutter/plugin…
BeMacized Jun 16, 2021
84d6db2
Update packages/camera/camera/android/src/main/java/io/flutter/plugin…
BeMacized Jun 16, 2021
071e879
Update packages/camera/camera/android/src/main/java/io/flutter/plugin…
BeMacized Jun 16, 2021
273762b
Update packages/camera/camera/android/src/test/java/io/flutter/plugin…
BeMacized Jun 16, 2021
e9e9bc5
Update packages/camera/camera/android/src/test/java/io/flutter/plugin…
BeMacized Jun 16, 2021
1af5437
Update packages/camera/camera/android/src/test/java/io/flutter/plugin…
BeMacized Jun 16, 2021
b49b743
Added documentation to DartMessenger
mvanbeusekom Jun 16, 2021
5b8c0d8
Update packages/camera/camera/android/src/main/java/io/flutter/plugin…
BeMacized Jun 16, 2021
62a2f21
Add missing CaptureTimeoutsWrapper documentation
BeMacized Jun 16, 2021
43c0716
Update packages/camera/camera/android/src/main/java/io/flutter/plugin…
BeMacized Jun 16, 2021
24c6c9a
Added documentation to the CameraCaptureCallback
mvanbeusekom Jun 16, 2021
fc2d78b
Merge branch 'camera-android/supporting_functionality' of github.com:…
mvanbeusekom Jun 16, 2021
b2536d4
Add missing documentation for ImageSaver runnable
BeMacized Jun 16, 2021
1748503
Merge remote-tracking branch 'origin/camera-android/supporting_functi…
BeMacized Jun 16, 2021
3118680
Update packages/camera/camera/android/src/main/java/io/flutter/plugin…
BeMacized Jun 16, 2021
7dbbdce
Added documentation to the CameraFeatureFactory
mvanbeusekom Jun 16, 2021
2b2bea3
Configure log tag in one place and optimised loggin
mvanbeusekom Jun 16, 2021
96d285b
Android rework finalization (wip)
BeMacized Jun 16, 2021
81920e0
Progress on final implementation of android rework
BeMacized Jun 16, 2021
6fe67da
Update tests
BeMacized Jun 16, 2021
7f0180e
Accept cameraName as String
mvanbeusekom Jun 16, 2021
24af367
Format
mvanbeusekom Jun 16, 2021
a987711
Changes required for integrating main camera class
BeMacized Jun 16, 2021
66a713d
Merge branch 'camera-android/fps_resolution_sensor_features' into cam…
BeMacized Jun 16, 2021
ce9df6c
Changes required for integrating main camera class
BeMacized Jun 16, 2021
32cb969
Remove debug statement
BeMacized Jun 16, 2021
44acbf7
Merge branch 'camera-android/supporting_functionality' into camera-an…
BeMacized Jun 16, 2021
dd3416b
Updated pubspec version and changelog
BeMacized Jun 16, 2021
d215ac7
Merge branch 'master' into camera-android/supporting_functionality
BeMacized Jun 22, 2021
d10397a
Merge branch 'camera-android/supporting_functionality' into camera-an…
BeMacized Jun 22, 2021
914b187
Merge branch 'master' into camera-android/supporting_functionality
BeMacized Jun 24, 2021
6e13430
Merge branch 'camera-android/supporting_functionality' into camera-an…
BeMacized Jun 24, 2021
9282d9a
Remove unused classes after refactor
BeMacized Jun 28, 2021
cb3a35c
Fix camera orientation issues
BeMacized Jun 28, 2021
5cfbf1c
Merge branch 'camera-android/final-rework-implementation' into fix/ca…
BeMacized Jun 28, 2021
5e3eac8
Fix unit tests
BeMacized Jun 29, 2021
9779a28
Fix rotation issues with exposure- and focus point features.
BeMacized Jul 8, 2021
90000ce
Fix unit tests & Format
BeMacized Jul 12, 2021
3b7f053
Add unit tests for metering rectangle rotation
BeMacized Jul 12, 2021
6bb305e
Merge branch 'master' into camera-android/final-rework-implementation
BeMacized Jul 12, 2021
8e44421
Merge branch 'camera-android/final-rework-implementation' into fix/ca…
BeMacized Jul 12, 2021
36d7173
Revert adjustments to platform interface to prevent unnecessary break…
BeMacized Jul 13, 2021
a2607d1
Revert naming refactor
BeMacized Jul 13, 2021
9fb1019
Update project.pbxproj
BeMacized Jul 13, 2021
777c696
Undo version bump
BeMacized Jul 13, 2021
6c8f16e
Merge branch 'camera-android/final-rework-implementation' into fix/ca…
BeMacized Jul 13, 2021
5d9fb6d
Updated changelog and pubspec version
BeMacized Jul 13, 2021
890605a
Merge branch 'fix/camera-orientation' into camera-android/final-rewor…
BeMacized Jul 13, 2021
7c916c2
Merge branch 'master' into camera-android/final-rework-implementation
BeMacized Jul 22, 2021
a3adf8f
Expand camera platform interface to support pausing the camera preview.
BeMacized Jul 26, 2021
98378d3
Add Android & iOS implementations for pausing the camera preview
BeMacized Jul 26, 2021
d78cab8
Merge branch 'master' into camera/preview-pause-interface
BeMacized Jul 26, 2021
6d12128
Merge branch 'camera/preview-pause-interface' into camera/preview-pau…
BeMacized Jul 26, 2021
d11acf0
Merge branch 'master' into camera/preview-pause-impl
BeMacized Aug 24, 2021
08137da
Fix formatting
BeMacized Aug 24, 2021
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
6 changes: 6 additions & 0 deletions packages/camera/camera/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 0.9.0

* Complete rewrite of Android plugin to fix many capture, focus, flash, orientation and exposure issues.
* Fixed crash when opening front-facing cameras on some legacy android devices like Sony XZ.
* Android Flash mode works with full precapture sequence.

## 0.8.1+4

* Silenced warnings that may occur during build when using a very
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import android.os.Looper;
import android.util.Log;
import android.util.Size;
import android.util.SparseIntArray;
import android.view.Display;
import android.view.Surface;
import androidx.annotation.NonNull;
Expand Down Expand Up @@ -95,18 +94,8 @@ interface ErrorCallback {
class Camera implements CameraCaptureCallback.CameraCaptureStateListener {
private static final String TAG = "Camera";

/** Conversion from screen rotation to JPEG orientation. */
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();

private static final HashMap<String, Integer> supportedImageFormats;

static {
ORIENTATIONS.append(Surface.ROTATION_0, 90);
ORIENTATIONS.append(Surface.ROTATION_90, 0);
ORIENTATIONS.append(Surface.ROTATION_180, 270);
ORIENTATIONS.append(Surface.ROTATION_270, 180);
}

// Current supported outputs
static {
supportedImageFormats = new HashMap<>();
Expand Down Expand Up @@ -209,20 +198,23 @@ public Camera(
cameraFeatureFactory.createExposureLockFeature(cameraProperties));
this.cameraFeatures.setExposureOffset(
cameraFeatureFactory.createExposureOffsetFeature(cameraProperties));
SensorOrientationFeature sensorOrientationFeature =
cameraFeatureFactory.createSensorOrientationFeature(
cameraProperties, activity, dartMessenger);
this.cameraFeatures.setSensorOrientation(sensorOrientationFeature);
this.cameraFeatures.setExposurePoint(
cameraFeatureFactory.createExposurePointFeature(cameraProperties));
cameraFeatureFactory.createExposurePointFeature(
cameraProperties, sensorOrientationFeature));
this.cameraFeatures.setFlash(cameraFeatureFactory.createFlashFeature(cameraProperties));
this.cameraFeatures.setFocusPoint(
cameraFeatureFactory.createFocusPointFeature(cameraProperties));
cameraFeatureFactory.createFocusPointFeature(cameraProperties, sensorOrientationFeature));
this.cameraFeatures.setFpsRange(cameraFeatureFactory.createFpsRangeFeature(cameraProperties));
this.cameraFeatures.setNoiseReduction(
cameraFeatureFactory.createNoiseReductionFeature(cameraProperties));
this.cameraFeatures.setResolution(
cameraFeatureFactory.createResolutionFeature(
cameraProperties, resolutionPreset, cameraProperties.getCameraName()));
this.cameraFeatures.setSensorOrientation(
cameraFeatureFactory.createSensorOrientationFeature(
cameraProperties, activity, dartMessenger));

this.cameraFeatures.setZoomLevel(cameraFeatureFactory.createZoomLevelFeature(cameraProperties));

// Create capture callback
Expand Down Expand Up @@ -271,8 +263,8 @@ private void prepareMediaRecorder(String outputFilePath) throws IOException {
.setEnableAudio(enableAudio)
.setMediaOrientation(
lockedOrientation == null
? getDeviceOrientationManager().getMediaOrientation()
: getDeviceOrientationManager().getMediaOrientation(lockedOrientation))
? getDeviceOrientationManager().getVideoOrientation()
: getDeviceOrientationManager().getVideoOrientation(lockedOrientation))
.build();
}

Expand Down Expand Up @@ -596,8 +588,14 @@ private void takePictureAfterPrecapture() {
updateBuilderSettings(stillBuilder);

// Orientation
int rotation = getDefaultDisplay().getRotation();
stillBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation(rotation));
final PlatformChannel.DeviceOrientation lockedOrientation =
((SensorOrientationFeature) cameraFeatures.getSensorOrientation())
.getLockedCaptureOrientation();
stillBuilder.set(
CaptureRequest.JPEG_ORIENTATION,
lockedOrientation == null
? getDeviceOrientationManager().getPhotoOrientation()
: getDeviceOrientationManager().getPhotoOrientation(lockedOrientation));

CameraCaptureSession.CaptureCallback captureCallback =
new CameraCaptureSession.CaptureCallback() {
Expand Down Expand Up @@ -665,21 +663,6 @@ private void stopBackgroundThread() {
}
}

/**
* Retrieves the JPEG orientation from the specified screen rotation.
*
* @param rotation The screen rotation.
* @return The JPEG orientation (one of 0, 90, 270, and 360)
*/
private int getOrientation(int rotation) {
// Sensor orientation is 90 for most devices, or 270 for some devices (eg. Nexus 5X)
// We have to take that into account and rotate JPEG properly.
// For devices with orientation of 90, we simply return our mapping from ORIENTATIONS.
// For devices with orientation of 270, we need to rotate the JPEG 180 degrees.
final Integer sensorOrientation = cameraFeatures.getSensorOrientation().getValue();
return (ORIENTATIONS.get(rotation) + sensorOrientation + 270) % 360;
}

/** Start capturing a picture, doing autofocus first. */
private void runPictureAutoFocus() {
Log.i(TAG, "runPictureAutoFocus");
Expand Down Expand Up @@ -908,7 +891,7 @@ public double getExposureOffsetStepSize() {
* @param result Flutter result.
* @param newMode New mode.
*/
public void setFocusMode(@NonNull final Result result, FocusMode newMode) {
public void setFocusMode(final Result result, FocusMode newMode) {
final AutoFocusFeature autoFocusFeature = cameraFeatures.getAutoFocus();
autoFocusFeature.setValue(newMode);
autoFocusFeature.updateBuilder(previewRequestBuilder);
Expand All @@ -930,7 +913,9 @@ public void setFocusMode(@NonNull final Result result, FocusMode newMode) {
captureSession.setRepeatingRequest(
previewRequestBuilder.build(), null, backgroundHandler);
} catch (CameraAccessException e) {
result.error("setFocusModeFailed", "Error setting focus mode: " + e.getMessage(), null);
if (result != null) {
result.error("setFocusModeFailed", "Error setting focus mode: " + e.getMessage(), null);
}
}
break;

Expand All @@ -940,7 +925,9 @@ public void setFocusMode(@NonNull final Result result, FocusMode newMode) {
break;
}

result.success(null);
if (result != null) {
result.success(null);
}
}

/**
Expand All @@ -957,6 +944,8 @@ public void setFocusPoint(@NonNull final Result result, Point point) {
refreshPreviewCaptureSession(
() -> result.success(null),
(code, message) -> result.error("setFocusPointFailed", "Could not set focus point.", null));

this.setFocusMode(null, cameraFeatures.getAutoFocus().getValue());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import android.util.Size;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import io.flutter.embedding.engine.systemchannels.PlatformChannel;
import java.util.Arrays;

/**
Expand Down Expand Up @@ -69,11 +70,32 @@ && supportsDistortionCorrection(cameraProperties)) {
* boundaries.
*/
public static MeteringRectangle convertPointToMeteringRectangle(
@NonNull Size boundaries, double x, double y) {
@NonNull Size boundaries,
double x,
double y,
@NonNull PlatformChannel.DeviceOrientation orientation) {
assert (boundaries.getWidth() > 0 && boundaries.getHeight() > 0);
assert (x >= 0 && x <= 1);
assert (y >= 0 && y <= 1);

// Rotate the coordinates to match the device orientation
double oldX = x, oldY = y;
switch (orientation) {
case PORTRAIT_UP: // 90 ccw
y = 1 - oldX;
x = oldY;
break;
case PORTRAIT_DOWN: // 90 cw
x = 1 - oldY;
y = oldX;
break;
case LANDSCAPE_LEFT:
// No rotation required
break;
case LANDSCAPE_RIGHT: // 180
x = 1 - x;
y = 1 - y;
break;
}
// Interpolate the target coordinate.
int targetX = (int) Math.round(x * ((double) (boundaries.getWidth() - 1)));
int targetY = (int) Math.round(y * ((double) (boundaries.getHeight() - 1)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,13 @@ ResolutionFeature createResolutionFeature(
*
* @param cameraProperties instance of the CameraProperties class containing information about the
* cameras features.
* @param sensorOrientationFeature instance of the SensorOrientationFeature class containing
* information about the sensor and device orientation.
* @return newly created instance of the FocusPointFeature class.
*/
FocusPointFeature createFocusPointFeature(@NonNull CameraProperties cameraProperties);
FocusPointFeature createFocusPointFeature(
@NonNull CameraProperties cameraProperties,
@NonNull SensorOrientationFeature sensorOrientationFeature);

/**
* Creates a new instance of the FPS range feature.
Expand Down Expand Up @@ -126,9 +130,13 @@ SensorOrientationFeature createSensorOrientationFeature(
*
* @param cameraProperties instance of the CameraProperties class containing information about the
* cameras features.
* @param sensorOrientationFeature instance of the SensorOrientationFeature class containing
* information about the sensor and device orientation.
* @return newly created instance of the ExposurePointFeature class.
*/
ExposurePointFeature createExposurePointFeature(@NonNull CameraProperties cameraProperties);
ExposurePointFeature createExposurePointFeature(
@NonNull CameraProperties cameraProperties,
@NonNull SensorOrientationFeature sensorOrientationFeature);

/**
* Creates a new instance of the noise reduction feature.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@ public ResolutionFeature createResolutionFeature(
}

@Override
public FocusPointFeature createFocusPointFeature(@NonNull CameraProperties cameraProperties) {
return new FocusPointFeature(cameraProperties);
public FocusPointFeature createFocusPointFeature(
@NonNull CameraProperties cameraProperties,
@NonNull SensorOrientationFeature sensorOrientationFeature) {
return new FocusPointFeature(cameraProperties, sensorOrientationFeature);
}

@Override
Expand All @@ -83,8 +85,9 @@ public ZoomLevelFeature createZoomLevelFeature(@NonNull CameraProperties cameraP

@Override
public ExposurePointFeature createExposurePointFeature(
@NonNull CameraProperties cameraProperties) {
return new ExposurePointFeature(cameraProperties);
@NonNull CameraProperties cameraProperties,
@NonNull SensorOrientationFeature sensorOrientationFeature) {
return new ExposurePointFeature(cameraProperties, sensorOrientationFeature);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,30 @@
import android.hardware.camera2.params.MeteringRectangle;
import android.util.Size;
import androidx.annotation.NonNull;
import io.flutter.embedding.engine.systemchannels.PlatformChannel;
import io.flutter.plugins.camera.CameraProperties;
import io.flutter.plugins.camera.CameraRegionUtils;
import io.flutter.plugins.camera.features.CameraFeature;
import io.flutter.plugins.camera.features.Point;
import io.flutter.plugins.camera.features.sensororientation.SensorOrientationFeature;

/** Exposure point controls where in the frame exposure metering will come from. */
public class ExposurePointFeature extends CameraFeature<Point> {

private Size cameraBoundaries;
private Point exposurePoint;
private MeteringRectangle exposureRectangle;
private final SensorOrientationFeature sensorOrientationFeature;

/**
* Creates a new instance of the {@link ExposurePointFeature}.
*
* @param cameraProperties Collection of the characteristics for the current camera device.
*/
public ExposurePointFeature(CameraProperties cameraProperties) {
public ExposurePointFeature(
CameraProperties cameraProperties, SensorOrientationFeature sensorOrientationFeature) {
super(cameraProperties);
this.sensorOrientationFeature = sensorOrientationFeature;
}

/**
Expand Down Expand Up @@ -80,9 +85,15 @@ private void buildExposureRectangle() {
if (this.exposurePoint == null) {
this.exposureRectangle = null;
} else {
PlatformChannel.DeviceOrientation orientation =
this.sensorOrientationFeature.getLockedCaptureOrientation();
if (orientation == null) {
orientation =
this.sensorOrientationFeature.getDeviceOrientationManager().getLastUIOrientation();
}
this.exposureRectangle =
CameraRegionUtils.convertPointToMeteringRectangle(
this.cameraBoundaries, this.exposurePoint.x, this.exposurePoint.y);
this.cameraBoundaries, this.exposurePoint.x, this.exposurePoint.y, orientation);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,30 @@
import android.hardware.camera2.params.MeteringRectangle;
import android.util.Size;
import androidx.annotation.NonNull;
import io.flutter.embedding.engine.systemchannels.PlatformChannel;
import io.flutter.plugins.camera.CameraProperties;
import io.flutter.plugins.camera.CameraRegionUtils;
import io.flutter.plugins.camera.features.CameraFeature;
import io.flutter.plugins.camera.features.Point;
import io.flutter.plugins.camera.features.sensororientation.SensorOrientationFeature;

/** Focus point controls where in the frame focus will come from. */
public class FocusPointFeature extends CameraFeature<Point> {

private Size cameraBoundaries;
private Point focusPoint;
private MeteringRectangle focusRectangle;
private final SensorOrientationFeature sensorOrientationFeature;

/**
* Creates a new instance of the {@link FocusPointFeature}.
*
* @param cameraProperties Collection of the characteristics for the current camera device.
*/
public FocusPointFeature(CameraProperties cameraProperties) {
public FocusPointFeature(
CameraProperties cameraProperties, SensorOrientationFeature sensorOrientationFeature) {
super(cameraProperties);
this.sensorOrientationFeature = sensorOrientationFeature;
}

/**
Expand Down Expand Up @@ -80,9 +85,15 @@ private void buildFocusRectangle() {
if (this.focusPoint == null) {
this.focusRectangle = null;
} else {
PlatformChannel.DeviceOrientation orientation =
this.sensorOrientationFeature.getLockedCaptureOrientation();
if (orientation == null) {
orientation =
this.sensorOrientationFeature.getDeviceOrientationManager().getLastUIOrientation();
}
this.focusRectangle =
CameraRegionUtils.convertPointToMeteringRectangle(
this.cameraBoundaries, this.focusPoint.x, this.focusPoint.y);
this.cameraBoundaries, this.focusPoint.x, this.focusPoint.y, orientation);
}
}
}
Loading