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

Migrate camera/android from SurfaceTexture->SurfaceProducer. #6461

Merged
merged 15 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from 10 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
7 changes: 4 additions & 3 deletions packages/camera/camera_android/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## NEXT
## 0.10.10

* Updates minimum supported SDK version to Flutter 3.16/Dart 3.2.
* Updates minimum supported SDK version to Flutter 3.22/Dart 3.2.
* [Supports Impeller](https://docs.flutter.dev/release/breaking-changes/android-surface-plugins)
jonahwilliams marked this conversation as resolved.
Show resolved Hide resolved

## 0.10.9+2

Expand Down Expand Up @@ -35,7 +36,7 @@

## 0.10.8+14

* Fixes `pausePreview` null pointer error. `pausePreview` should not be called
* Fixes `pausePreview` null pointer error. `pausePreview` should not be called
when camera is closed or not configured.
* Updates minimum supported SDK version to Flutter 3.10/Dart 3.0.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import android.app.Activity;
import android.content.Context;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraDevice;
Expand Down Expand Up @@ -63,7 +62,7 @@
import io.flutter.plugins.camera.media.MediaRecorderBuilder;
import io.flutter.plugins.camera.types.CameraCaptureProperties;
import io.flutter.plugins.camera.types.CaptureTimeoutsWrapper;
import io.flutter.view.TextureRegistry.SurfaceTextureEntry;
import io.flutter.view.TextureRegistry;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
Expand Down Expand Up @@ -113,7 +112,7 @@ class Camera
*/
@VisibleForTesting int initialCameraFacing;

@VisibleForTesting final SurfaceTextureEntry flutterTexture;
@VisibleForTesting final TextureRegistry.SurfaceProducer surfaceProducer;
private final VideoCaptureSettings videoCaptureSettings;
private final Context applicationContext;
final DartMessenger dartMessenger;
Expand Down Expand Up @@ -214,17 +213,16 @@ public VideoCaptureSettings(@NonNull ResolutionPreset resolutionPreset, boolean

public Camera(
final Activity activity,
final SurfaceTextureEntry flutterTexture,
final TextureRegistry.SurfaceProducer surfaceProducer,
final CameraFeatureFactory cameraFeatureFactory,
final DartMessenger dartMessenger,
final CameraProperties cameraProperties,
final VideoCaptureSettings videoCaptureSettings) {

if (activity == null) {
throw new IllegalStateException("No activity available!");
}
this.activity = activity;
this.flutterTexture = flutterTexture;
this.surfaceProducer = surfaceProducer;
this.dartMessenger = dartMessenger;
this.applicationContext = activity.getApplicationContext();
this.cameraProperties = cameraProperties;
Expand All @@ -243,7 +241,6 @@ public Camera(
if (videoCaptureSettings.fps != null && videoCaptureSettings.fps.intValue() > 0) {
recordingFps = videoCaptureSettings.fps;
} else {

if (SdkCapabilityChecker.supportsEncoderProfiles()) {
EncoderProfiles encoderProfiles = getRecordingProfile();
if (encoderProfiles != null && encoderProfiles.getVideoProfiles().size() > 0) {
Expand All @@ -256,7 +253,6 @@ public Camera(
}

if (recordingFps != null && recordingFps.intValue() > 0) {

final FpsRangeFeature fpsRange = new FpsRangeFeature(cameraProperties);
fpsRange.setValue(new Range<Integer>(recordingFps, recordingFps));
this.cameraFeatures.setFpsRange(fpsRange);
Expand Down Expand Up @@ -307,8 +303,9 @@ private void prepareMediaRecorder(String outputFilePath) throws IOException {

MediaRecorderBuilder mediaRecorderBuilder;

// TODO(camsim99): Revert changes that allow legacy code to be used when recordingProfile is null
// once this has largely been fixed on the Android side. https://github.com/flutter/flutter/issues/119668
// TODO(camsim99): Revert changes that allow legacy code to be used when recordingProfile is
// null once this has largely been fixed on the Android side.
// https://github.com/flutter/flutter/issues/119668
if (SdkCapabilityChecker.supportsEncoderProfiles() && getRecordingProfile() != null) {
mediaRecorderBuilder =
new MediaRecorderBuilder(
Expand Down Expand Up @@ -386,7 +383,8 @@ public void onOpened(@NonNull CameraDevice device) {
cameraDevice = new DefaultCameraDeviceWrapper(device);
try {
startPreview();
if (!recordingVideo) { // only send initialization if we werent already recording and switching cameras
if (!recordingVideo) { // only send initialization if we werent already recording and
// switching cameras
dartMessenger.sendCameraInitializedEvent(
resolutionFeature.getPreviewSize().getWidth(),
resolutionFeature.getPreviewSize().getHeight(),
Expand Down Expand Up @@ -470,11 +468,10 @@ private void createCaptureSession(

// Build Flutter surface to render to.
ResolutionFeature resolutionFeature = cameraFeatures.getResolution();
SurfaceTexture surfaceTexture = flutterTexture.surfaceTexture();
surfaceTexture.setDefaultBufferSize(
surfaceProducer.setSize(
resolutionFeature.getPreviewSize().getWidth(),
resolutionFeature.getPreviewSize().getHeight());
Surface flutterSurface = new Surface(surfaceTexture);
Surface flutterSurface = surfaceProducer.getSurface();
previewRequestBuilder.addTarget(flutterSurface);

List<Surface> remainingSurfaces = Arrays.asList(surfaces);
Expand Down Expand Up @@ -1160,7 +1157,8 @@ public void resumePreview() {
}

public void startPreview() throws CameraAccessException, InterruptedException {
// If recording is already in progress, the camera is being flipped, so send it through the VideoRenderer to keep the correct orientation.
// If recording is already in progress, the camera is being flipped, so send it through the
// VideoRenderer to keep the correct orientation.
if (recordingVideo) {
startPreviewWithVideoRendererStream();
} else {
Expand Down Expand Up @@ -1193,7 +1191,6 @@ private void startPreviewWithVideoRendererStream()
}

if (cameraProperties.getLensFacing() != initialCameraFacing) {

// If the new camera is facing the opposite way than the initial recording,
// the rotation should be flipped 180 degrees.
rotation = (rotation + 180) % 360;
Expand Down Expand Up @@ -1361,13 +1358,13 @@ public void uncaughtException(Thread thread, Throwable ex) {

public void setDescriptionWhileRecording(
@NonNull final Result result, CameraProperties properties) {

if (!recordingVideo) {
result.error("setDescriptionWhileRecordingFailed", "Device was not recording", null);
return;
}

// See VideoRenderer.java; support for this EGL extension is required to switch camera while recording.
// See VideoRenderer.java; support for this EGL extension is required to switch camera while
// recording.
if (!SdkCapabilityChecker.supportsEglRecordableAndroid()) {
result.error(
"setDescriptionWhileRecordingFailed",
Expand Down Expand Up @@ -1400,7 +1397,7 @@ public void dispose() {
Log.i(TAG, "dispose");

close();
flutterTexture.release();
surfaceProducer.release();
getDeviceOrientationManager().stop();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -393,27 +393,25 @@ private void instantiateCamera(MethodCall call, Result result) throws CameraAcce
Integer videoBitrate = call.argument("videoBitrate");
Integer audioBitrate = call.argument("audioBitrate");

TextureRegistry.SurfaceTextureEntry flutterSurfaceTexture =
textureRegistry.createSurfaceTexture();
TextureRegistry.SurfaceProducer surfaceProducer = textureRegistry.createSurfaceProducer();
DartMessenger dartMessenger =
new DartMessenger(
messenger, flutterSurfaceTexture.id(), new Handler(Looper.getMainLooper()));
new DartMessenger(messenger, surfaceProducer.id(), new Handler(Looper.getMainLooper()));
CameraProperties cameraProperties =
new CameraPropertiesImpl(cameraName, CameraUtils.getCameraManager(activity));
ResolutionPreset resolutionPreset = ResolutionPreset.valueOf(preset);

camera =
new Camera(
activity,
flutterSurfaceTexture,
surfaceProducer,
new CameraFeatureFactoryImpl(),
dartMessenger,
cameraProperties,
new Camera.VideoCaptureSettings(
resolutionPreset, enableAudio, fps, videoBitrate, audioBitrate));

Map<String, Object> reply = new HashMap<>();
reply.put("cameraId", flutterSurfaceTexture.id());
reply.put("cameraId", surfaceProducer.id());
result.success(reply);
}

Expand Down
Loading