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] Implement Image Streaming #3454

Merged
merged 73 commits into from
Apr 28, 2023
Merged
Show file tree
Hide file tree
Changes from 69 commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
6125eca
Recreating image capture impl from flutter/plugins
camsim99 Feb 23, 2023
5be1371
Merge remote-tracking branch 'upstream/main' into camx_imgcap
camsim99 Feb 23, 2023
b2fce3d
Fix integration tesT
camsim99 Feb 23, 2023
ed62a9a
Merge branch 'main' into camx_imgcap
camsim99 Feb 23, 2023
2e3027b
Analyzer pt 2
camsim99 Feb 23, 2023
fbd3fe5
Merge branch 'camx_imgcap' of github.com:camsim99/packages into camx_…
camsim99 Feb 23, 2023
dfa477e
Personal cleanup
camsim99 Feb 23, 2023
a651b92
Add initialization of controller
camsim99 Feb 24, 2023
884fd6c
Merge remote-tracking branch 'upstream/main' into camx_imgcap
camsim99 Feb 24, 2023
d5f8b91
Modify some docs
camsim99 Feb 24, 2023
060b7e5
Address review
camsim99 Mar 2, 2023
ff50c70
Merge remote-tracking branch 'upstream/main' into camx_imgcap
camsim99 Mar 2, 2023
fe6f1fc
Fix analyze
camsim99 Mar 2, 2023
e2643ae
Update packages/camera/camera_android_camerax/android/src/main/java/i…
camsim99 Mar 3, 2023
b7194f7
Update packages/camera/camera_android_camerax/lib/src/image_capture.dart
camsim99 Mar 3, 2023
dadc230
Start addressing review
camsim99 Mar 6, 2023
d15e1d4
Finish addressing review
camsim99 Mar 7, 2023
6dc2b77
Fix analyze
camsim99 Mar 7, 2023
f826b62
Generate mocks on stable
camsim99 Mar 7, 2023
0f7f29a
Fix/add tests
camsim99 Mar 7, 2023
1e9739b
Add isBound dart test
camsim99 Mar 7, 2023
83d6969
Start impl
camsim99 Mar 13, 2023
0f387e2
Add image analysis files
camsim99 Mar 13, 2023
0bf4f9a
Start filling in image streaming info
camsim99 Mar 13, 2023
97912fc
More dev
camsim99 Mar 15, 2023
b889e98
Dev
camsim99 Mar 16, 2023
e96c2ec
Fix flutter api
camsim99 Mar 20, 2023
cc2fcbe
Binding refactor
camsim99 Mar 22, 2023
00c51b1
Merge remote-tracking branch 'upstream/main' into camx_imgstr
camsim99 Mar 24, 2023
1e13e53
Undo format changes and change to example
camsim99 Mar 24, 2023
c37db5c
Start fixing ci errors
camsim99 Mar 24, 2023
80753a9
Fix fl analyze
camsim99 Mar 24, 2023
9edf9ac
Merge remote-tracking branch 'upstream/main' into camx_imgstr
camsim99 Mar 27, 2023
7ce175e
Finish implementation
camsim99 Mar 27, 2023
cb62063
Generate mocks
camsim99 Mar 27, 2023
8ccc7ed
Start adding tests
camsim99 Mar 28, 2023
2220bda
Merge remote-tracking branch 'upstream/main' into camx_imgstr
camsim99 Mar 28, 2023
a27cd4c
Start adding tests
camsim99 Mar 28, 2023
9d74956
Add file
camsim99 Mar 28, 2023
64b190e
Add java test
camsim99 Mar 28, 2023
fea7e98
Add tests
camsim99 Mar 28, 2023
22f271b
self review
camsim99 Mar 28, 2023
3867ce0
Fix analyzer and formatting
camsim99 Mar 29, 2023
03a2f6d
Merge remote-tracking branch 'upstream/main' into camx_imgstr
camsim99 Mar 29, 2023
8d08cff
Wrapping with generator
camsim99 Apr 11, 2023
c7c2e2f
Add more implementation
camsim99 Apr 14, 2023
f478e31
Correct autogenerator on dart classes
camsim99 Apr 18, 2023
9877601
Correct generator on java files
camsim99 Apr 18, 2023
f334259
Fix plugin code minus todos
camsim99 Apr 19, 2023
752c8ba
Make fixes required to build apk
camsim99 Apr 19, 2023
3dbd87d
Merge remote-tracking branch 'upstream/main' into camx_imgstr
camsim99 Apr 19, 2023
62b1925
Fix java tests
camsim99 Apr 19, 2023
14cc602
Fix java test names
camsim99 Apr 19, 2023
1f420da
Get feature working
camsim99 Apr 19, 2023
c550fc0
Fix plugin test
camsim99 Apr 21, 2023
e3fa142
Fix analyzer test
camsim99 Apr 21, 2023
8dc333c
Fix plane proxy test
camsim99 Apr 21, 2023
d5bfdac
Fix image proxy test
camsim99 Apr 21, 2023
6034265
Fix image analysis test
camsim99 Apr 21, 2023
a719034
Fix analyze
camsim99 Apr 22, 2023
193ce9c
Format
camsim99 Apr 22, 2023
914e244
Change getters to params, fix java tests
camsim99 Apr 26, 2023
b704ff5
Fix analyze, dart tests
camsim99 Apr 26, 2023
6bae352
Add nonnull annotation for lint
camsim99 Apr 26, 2023
e4f522e
Bump test rerun
camsim99 Apr 26, 2023
9d70b2e
Merge remote-tracking branch 'upstream/main' into camx_imgstr
camsim99 Apr 26, 2023
f2a6167
Add annotations, try fix for test
camsim99 Apr 27, 2023
c42f7a1
Formatting
camsim99 Apr 27, 2023
402af7b
Add annotation
camsim99 Apr 27, 2023
c711743
Revert instance manager integration test changes
camsim99 Apr 27, 2023
5091aa3
Address review, mock test instance manager host api for failing test
camsim99 Apr 27, 2023
c6c5753
Remove asserts in plugin code
camsim99 Apr 27, 2023
619a165
Fix comment
camsim99 Apr 28, 2023
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 @@ -18,3 +18,4 @@
* Implements image capture.
* Fixes cast of CameraInfo to fix integration test failure.
* Updates internal Java InstanceManager to only stop finalization callbacks when stopped.
* Implements image streaming.
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// 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.annotation.VisibleForTesting;
import androidx.camera.core.ImageAnalysis;
import androidx.camera.core.ImageProxy;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.AnalyzerFlutterApi;
import java.util.Objects;

/**
* Flutter API implementation for {@link ImageAnalysis.Analyzer}.
*
* <p>This class may handle adding native instances that are attached to a Dart instance or passing
* arguments of callbacks methods to a Dart instance.
*/
public class AnalyzerFlutterApiImpl {
private final BinaryMessenger binaryMessenger;
private final InstanceManager instanceManager;
private AnalyzerFlutterApi api;

/**
* Constructs a {@link AnalyzerFlutterApiImpl}.
*
* @param binaryMessenger used to communicate with Dart over asynchronous messages
* @param instanceManager maintains instances stored to communicate with attached Dart objects
*/
public AnalyzerFlutterApiImpl(
@NonNull BinaryMessenger binaryMessenger, @NonNull InstanceManager instanceManager) {
this.binaryMessenger = binaryMessenger;
this.instanceManager = instanceManager;
api = new AnalyzerFlutterApi(binaryMessenger);
}

/**
* Stores the {@link ImageAnalysis.Analyzer} instance and notifies Dart to create and store a new
* {@code Analyzer} instance that is attached to this one. If {@code instance} has already been
* added, this method does nothing.
*/
public void create(
@NonNull ImageAnalysis.Analyzer instance, @NonNull AnalyzerFlutterApi.Reply<Void> callback) {
if (!instanceManager.containsInstance(instance)) {
api.create(instanceManager.addHostCreatedInstance(instance), callback);
}
}

/**
* Sends a message to Dart to call {@code Analyzer.analyze} on the Dart object representing
* `instance`.
*/
public void analyze(
@NonNull ImageAnalysis.Analyzer analyzerInstance,
@NonNull ImageProxy imageProxyInstance,
@NonNull AnalyzerFlutterApi.Reply<Void> callback) {
api.analyze(
Objects.requireNonNull(instanceManager.getIdentifierForStrongReference(analyzerInstance)),
Objects.requireNonNull(instanceManager.getIdentifierForStrongReference(imageProxyInstance)),
callback);
}

/**
* Sets the Flutter API used to send messages to Dart.
*
* <p>This is only visible for testing.
*/
@VisibleForTesting
void setApi(@NonNull AnalyzerFlutterApi api) {
this.api = api;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// 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.annotation.VisibleForTesting;
import androidx.camera.core.ImageAnalysis;
import androidx.camera.core.ImageProxy;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.AnalyzerHostApi;

/**
* Host API implementation for {@link ImageAnalysis.Analyzer}.
*
* <p>This class may handle instantiating and adding native object instances that are attached to a
* Dart instance or handle method calls on the associated native class or an instance of the class.
*/
public class AnalyzerHostApiImpl implements AnalyzerHostApi {
private final BinaryMessenger binaryMessenger;
private final InstanceManager instanceManager;
private final AnalyzerProxy proxy;

/** Proxy for constructors and static method of {@link ImageAnalysis.Analyzer}. */
@VisibleForTesting
public static class AnalyzerProxy {

/** Creates an instance of {@link AnalyzerImpl}. */
@NonNull
public AnalyzerImpl create(
@NonNull BinaryMessenger binaryMessenger, @NonNull InstanceManager instanceManager) {
return new AnalyzerImpl(binaryMessenger, instanceManager);
}
}

/**
* Implementation of {@link ImageAnalysis.Analyzer} that passes arguments of callback methods to
* Dart.
*/
public static class AnalyzerImpl implements ImageAnalysis.Analyzer {
private BinaryMessenger binaryMessenger;
private InstanceManager instanceManager;
private AnalyzerFlutterApiImpl api;

@VisibleForTesting @NonNull public ImageProxyFlutterApiImpl imageProxyApi;

/**
* Constructs an instance of {@link ImageAnalysis.Analyzer} that passes arguments of callbacks
* methods to Dart.
*/
public AnalyzerImpl(
@NonNull BinaryMessenger binaryMessenger, @NonNull InstanceManager instanceManager) {
super();
this.binaryMessenger = binaryMessenger;
this.instanceManager = instanceManager;
api = new AnalyzerFlutterApiImpl(binaryMessenger, instanceManager);
imageProxyApi = new ImageProxyFlutterApiImpl(binaryMessenger, instanceManager);
}

@Override
public void analyze(@NonNull ImageProxy imageProxy) {
Long imageFormat = Long.valueOf(imageProxy.getFormat());
Long imageHeight = Long.valueOf(imageProxy.getHeight());
Long imageWidth = Long.valueOf(imageProxy.getWidth());
imageProxyApi.create(imageProxy, imageFormat, imageHeight, imageWidth, reply -> {});

api.analyze(this, imageProxy, reply -> {});
}

/**
* Flutter API used to send messages back to Dart.
*
* <p>This is only visible for testing.
*/
@VisibleForTesting
void setApi(@NonNull AnalyzerFlutterApiImpl api) {
this.api = api;
}
}

/**
* Constructs a {@link AnalyzerHostApiImpl}.
*
* @param binaryMessenger used to communicate with Dart over asynchronous messages
* @param instanceManager maintains instances stored to communicate with attached Dart objects
*/
public AnalyzerHostApiImpl(
@NonNull BinaryMessenger binaryMessenger, @NonNull InstanceManager instanceManager) {
this(binaryMessenger, instanceManager, new AnalyzerProxy());
}

/**
* Constructs a {@link AnalyzerHostApiImpl}.
*
* @param binaryMessenger used to communicate with Dart over asynchronous messages
* @param instanceManager maintains instances stored to communicate with attached Dart objects
* @param proxy proxy for constructors and static method of {@link ImageAnalysis.Analyzer}
*/
@VisibleForTesting
AnalyzerHostApiImpl(
@NonNull BinaryMessenger binaryMessenger,
@NonNull InstanceManager instanceManager,
@NonNull AnalyzerProxy proxy) {
this.binaryMessenger = binaryMessenger;
this.instanceManager = instanceManager;
this.proxy = proxy;
}

/**
* Creates an {@link AnalyzerProxy} that represents an {@link ImageAnalysis.Analyzer} instance
* with the specified identifier.
*/
@Override
public void create(@NonNull Long identifier) {
instanceManager.addDartCreatedInstance(
proxy.create(binaryMessenger, instanceManager), identifier);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public final class CameraAndroidCameraxPlugin implements FlutterPlugin, Activity
private InstanceManager instanceManager;
private FlutterPluginBinding pluginBinding;
private ProcessCameraProviderHostApiImpl processCameraProviderHostApi;
private ImageAnalysisHostApiImpl imageAnalysisHostApiImpl;
private ImageCaptureHostApiImpl imageCaptureHostApi;
public SystemServicesHostApiImpl systemServicesHostApi;

Expand Down Expand Up @@ -56,6 +57,12 @@ void setUp(BinaryMessenger binaryMessenger, Context context, TextureRegistry tex
binaryMessenger, new PreviewHostApiImpl(binaryMessenger, instanceManager, textureRegistry));
imageCaptureHostApi = new ImageCaptureHostApiImpl(binaryMessenger, instanceManager, context);
GeneratedCameraXLibrary.ImageCaptureHostApi.setup(binaryMessenger, imageCaptureHostApi);
imageAnalysisHostApiImpl = new ImageAnalysisHostApiImpl(binaryMessenger, instanceManager);
GeneratedCameraXLibrary.ImageAnalysisHostApi.setup(binaryMessenger, imageAnalysisHostApiImpl);
GeneratedCameraXLibrary.AnalyzerHostApi.setup(
binaryMessenger, new AnalyzerHostApiImpl(binaryMessenger, instanceManager));
GeneratedCameraXLibrary.ImageProxyHostApi.setup(
binaryMessenger, new ImageProxyHostApiImpl(binaryMessenger, instanceManager));
}

@Override
Expand Down Expand Up @@ -113,5 +120,8 @@ public void updateContext(Context context) {
if (imageCaptureHostApi != null) {
processCameraProviderHostApi.setContext(context);
}
if (imageAnalysisHostApiImpl != null) {
imageAnalysisHostApiImpl.setContext(context);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,27 @@

import android.app.Activity;
import android.graphics.SurfaceTexture;
import android.util.Size;
import android.view.Surface;
import androidx.annotation.NonNull;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageAnalysis;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.Preview;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.ResolutionInfo;
import java.io.File;

/** Utility class used to create CameraX-related objects primarily for testing purposes. */
public class CameraXProxy {
/**
* Converts a {@link ResolutionInfo} instance to a {@link Size} for setting the target resolution
* of {@link UseCase}s.
*/
public static Size sizeFromResolution(@NonNull ResolutionInfo resolutionInfo) {
return new Size(resolutionInfo.getWidth().intValue(), resolutionInfo.getHeight().intValue());
}

public CameraSelector.Builder createCameraSelectorBuilder() {
return new CameraSelector.Builder();
}
Expand Down Expand Up @@ -58,7 +69,20 @@ public ImageCapture.Builder createImageCaptureBuilder() {
/**
* Creates an {@link ImageCapture.OutputFileOptions} to configure where to save a captured image.
*/
@NonNull
public ImageCapture.OutputFileOptions createImageCaptureOutputFileOptions(@NonNull File file) {
return new ImageCapture.OutputFileOptions.Builder(file).build();
}

/** Creates an instance of {@link ImageAnalysis.Builder}. */
@NonNull
public ImageAnalysis.Builder createImageAnalysisBuilder() {
return new ImageAnalysis.Builder();
}

/** Creates an array of {@code byte}s with the size provided. */
@NonNull
public byte[] getBytesFromBuffer(int size) {
return new byte[size];
}
}
Loading