Migrate `camera/android` from `SurfaceTexture`->`SurfaceProducer`. (#6461)
_**WIP**: We do not plan to land this PR until the next stable release (>= April 3rd 2024)_.
Work towards https://github.com/flutter/flutter/issues/145930.
## Details
Migrates uses of `createSurfaceTexture` to `createSurfaceProducer`, which is intended to have no change in behavior, but _does_ change the backend rendering path, so it will require more testing (and we're also open to minor API renames or changes before it becomes stable).
## Background
Android plugins previously requested a `SurfaceTexture` from the Android embedder, and used that to produce a `Surface` to render external textures on (i.e. `video_player`). This worked because 100% of Flutter applications on Android used OpenGLES (via our Skia backend), and `SurfaceTexture` is actually an (opaque) OpenGLES-texture.
Starting soon (roughly ~Q3, this is not a guarantee and just an estimate), Flutter on Android will start to use our new Impeller graphics backend, which on newer devices (`>= API_VERSION_28`), will default to the Vulkan, _not_ OpenGLES. In other words, `SurfaceTexture` will cease to work (it is possible, but non-trivial, to map an OpenGLES texture over to Vulkan).
After consultation with the Android team, they helped us understand that vending `SurfaceTexture` (the _consumer-side_ API) was never the right abstraction, and we should have been vending the _producer-side_ API, or `Surface` directly. The new `SurfaceProducer` API is exactly that - it generates a `Surface`, and similar to our platform view strategy, picks the "right" _consumer-side_ implementation details _for_ the user/plugin packages.
The new `SurfaceProducer` API has 2 possible rendering types (as an implementation detail):
- `SurfaceTexture`, for older OpenGLES devices, which works exactly as it does today.
- `ImageReader`, for newer OpenGLES _or_ Vulkan devices.
These are some subtle nuances in how these two APIs work differently (one example: https://github.com/flutter/flutter/issues/144407), but our theory at this point is we don't expect these changes to be observed by any users, and we have other ideas if necessary.
> [!NOTE]
> These invariants are [tested on CI in `flutter/engine`](https://github.com/flutter/engine/tree/main/testing/scenario_app/android#ci-configuration).
Points of contact:
- @matanlurey or @jonahwilliams (Flutter Engine)
- @johnmccutchan or @reidbaker (Flutter on Android)
diff --git a/packages/camera/camera_android/CHANGELOG.md b/packages/camera/camera_android/CHANGELOG.md
index dbf3789..102fe72 100644
--- a/packages/camera/camera_android/CHANGELOG.md
+++ b/packages/camera/camera_android/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.10.9+4
+
+* [Supports Impeller](https://docs.flutter.dev/release/breaking-changes/android-surface-plugins).
+
## 0.10.9+3
* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4.
@@ -36,7 +40,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.
diff --git a/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/Camera.java b/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/Camera.java
index 7668ec9..52c5e59 100644
--- a/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/Camera.java
+++ b/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/Camera.java
@@ -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;
@@ -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;
@@ -113,7 +112,7 @@
*/
@VisibleForTesting int initialCameraFacing;
- @VisibleForTesting final SurfaceTextureEntry flutterTexture;
+ @VisibleForTesting final TextureRegistry.SurfaceProducer surfaceProducer;
private final VideoCaptureSettings videoCaptureSettings;
private final Context applicationContext;
final DartMessenger dartMessenger;
@@ -214,17 +213,16 @@
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;
@@ -243,7 +241,6 @@
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) {
@@ -256,7 +253,6 @@
}
if (recordingFps != null && recordingFps.intValue() > 0) {
-
final FpsRangeFeature fpsRange = new FpsRangeFeature(cameraProperties);
fpsRange.setValue(new Range<Integer>(recordingFps, recordingFps));
this.cameraFeatures.setFpsRange(fpsRange);
@@ -307,8 +303,9 @@
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(
@@ -386,7 +383,8 @@
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(),
@@ -470,11 +468,10 @@
// 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);
@@ -1160,7 +1157,8 @@
}
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 {
@@ -1193,7 +1191,6 @@
}
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;
@@ -1361,13 +1358,13 @@
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",
@@ -1400,7 +1397,7 @@
Log.i(TAG, "dispose");
close();
- flutterTexture.release();
+ surfaceProducer.release();
getDeviceOrientationManager().stop();
}
diff --git a/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/MethodCallHandlerImpl.java b/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/MethodCallHandlerImpl.java
index eae8c65..b3f4da8 100644
--- a/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/MethodCallHandlerImpl.java
+++ b/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/MethodCallHandlerImpl.java
@@ -393,11 +393,9 @@
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);
@@ -405,7 +403,7 @@
camera =
new Camera(
activity,
- flutterSurfaceTexture,
+ surfaceProducer,
new CameraFeatureFactoryImpl(),
dartMessenger,
cameraProperties,
@@ -413,7 +411,7 @@
resolutionPreset, enableAudio, fps, videoBitrate, audioBitrate));
Map<String, Object> reply = new HashMap<>();
- reply.put("cameraId", flutterSurfaceTexture.id());
+ reply.put("cameraId", surfaceProducer.id());
result.success(reply);
}
diff --git a/packages/camera/camera_android/android/src/test/java/io/flutter/plugins/camera/CameraTest.java b/packages/camera/camera_android/android/src/test/java/io/flutter/plugins/camera/CameraTest.java
index d2d90b7..9763808 100644
--- a/packages/camera/camera_android/android/src/test/java/io/flutter/plugins/camera/CameraTest.java
+++ b/packages/camera/camera_android/android/src/test/java/io/flutter/plugins/camera/CameraTest.java
@@ -32,7 +32,6 @@
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.camera.features.CameraFeatureFactory;
-import io.flutter.plugins.camera.features.CameraFeatures;
import io.flutter.plugins.camera.features.Point;
import io.flutter.plugins.camera.features.autofocus.AutoFocusFeature;
import io.flutter.plugins.camera.features.autofocus.FocusMode;
@@ -123,7 +122,6 @@
@Before
public void before() {
-
mockRangeConstruction = new RangeConstruction();
mockCameraProperties = mock(CameraProperties.class);
mockDartMessenger = mock(DartMessenger.class);
@@ -135,8 +133,8 @@
mockHandler = mock(Handler.class);
final Activity mockActivity = mock(Activity.class);
- final TextureRegistry.SurfaceTextureEntry mockFlutterTexture =
- mock(TextureRegistry.SurfaceTextureEntry.class);
+ final TextureRegistry.SurfaceProducer mockSurfaceProducer =
+ mock(TextureRegistry.SurfaceProducer.class);
final String cameraName = "1";
final ResolutionPreset resolutionPreset = ResolutionPreset.high;
final boolean enableAudio = false;
@@ -163,7 +161,7 @@
camera =
new Camera(
mockActivity,
- mockFlutterTexture,
+ mockSurfaceProducer,
mockCameraFeatureFactory,
mockDartMessenger,
mockCameraProperties,
@@ -195,8 +193,8 @@
@Test
public void shouldCreateCameraPluginAndSetAllFeatures() {
final Activity mockActivity = mock(Activity.class);
- final TextureRegistry.SurfaceTextureEntry mockFlutterTexture =
- mock(TextureRegistry.SurfaceTextureEntry.class);
+ final TextureRegistry.SurfaceProducer mockSurfaceProducer =
+ mock(TextureRegistry.SurfaceProducer.class);
final CameraFeatureFactory spyMockCameraFeatureFactory = spy(mockCameraFeatureFactory);
final String cameraName = "1";
final ResolutionPreset resolutionPreset = ResolutionPreset.high;
@@ -210,7 +208,7 @@
Camera camera =
new Camera(
mockActivity,
- mockFlutterTexture,
+ mockSurfaceProducer,
spyMockCameraFeatureFactory,
mockDartMessenger,
mockCameraProperties,
@@ -681,7 +679,6 @@
VideoRenderer mockVideoRenderer = mock(VideoRenderer.class);
ArrayList<CaptureRequest.Builder> mockRequestBuilders = new ArrayList<>();
mockRequestBuilders.add(mock(CaptureRequest.Builder.class));
- SurfaceTexture mockSurfaceTexture = mock(SurfaceTexture.class);
Size mockSize = mock(Size.class);
camera.recordingVideo = true;
camera.videoRenderer = mockVideoRenderer;
@@ -690,10 +687,8 @@
ImageReader mockPictureImageReader = mock(ImageReader.class);
camera.pictureImageReader = mockPictureImageReader;
- TextureRegistry.SurfaceTextureEntry cameraFlutterTexture = camera.flutterTexture;
ResolutionFeature resolutionFeature = mockCameraFeatureFactory.mockResolutionFeature;
- when(cameraFlutterTexture.surfaceTexture()).thenReturn(mockSurfaceTexture);
when(resolutionFeature.getPreviewSize()).thenReturn(mockSize);
camera.startPreview();
@@ -706,7 +701,6 @@
throws InterruptedException, CameraAccessException {
ArrayList<CaptureRequest.Builder> mockRequestBuilders = new ArrayList<>();
mockRequestBuilders.add(mock(CaptureRequest.Builder.class));
- SurfaceTexture mockSurfaceTexture = mock(SurfaceTexture.class);
Size mockSize = mock(Size.class);
ImageReader mockImageReader = mock(ImageReader.class);
camera.recordingVideo = false;
@@ -714,10 +708,8 @@
CameraDeviceWrapper fakeCamera = new FakeCameraDeviceWrapper(mockRequestBuilders);
camera.cameraDevice = fakeCamera;
- TextureRegistry.SurfaceTextureEntry cameraFlutterTexture = camera.flutterTexture;
ResolutionFeature resolutionFeature = mockCameraFeatureFactory.mockResolutionFeature;
- when(cameraFlutterTexture.surfaceTexture()).thenReturn(mockSurfaceTexture);
when(resolutionFeature.getPreviewSize()).thenReturn(mockSize);
when(mockImageReader.getSurface()).thenReturn(mock(Surface.class));
@@ -731,7 +723,6 @@
VideoRenderer mockVideoRenderer = mock(VideoRenderer.class);
ArrayList<CaptureRequest.Builder> mockRequestBuilders = new ArrayList<>();
mockRequestBuilders.add(mock(CaptureRequest.Builder.class));
- SurfaceTexture mockSurfaceTexture = mock(SurfaceTexture.class);
Size mockSize = mock(Size.class);
camera.recordingVideo = true;
camera.videoRenderer = mockVideoRenderer;
@@ -741,10 +732,8 @@
ImageReader mockPictureImageReader = mock(ImageReader.class);
camera.pictureImageReader = mockPictureImageReader;
- TextureRegistry.SurfaceTextureEntry cameraFlutterTexture = camera.flutterTexture;
ResolutionFeature resolutionFeature = mockCameraFeatureFactory.mockResolutionFeature;
- when(cameraFlutterTexture.surfaceTexture()).thenReturn(mockSurfaceTexture);
when(resolutionFeature.getPreviewSize()).thenReturn(mockSize);
when(mockCameraProperties.getLensFacing()).thenReturn(CameraMetadata.LENS_FACING_FRONT);
@@ -767,10 +756,8 @@
camera.cameraDevice = fakeCamera;
camera.imageStreamReader = mockImageStreamReader;
- TextureRegistry.SurfaceTextureEntry cameraFlutterTexture = camera.flutterTexture;
ResolutionFeature resolutionFeature = mockCameraFeatureFactory.mockResolutionFeature;
- when(cameraFlutterTexture.surfaceTexture()).thenReturn(mockSurfaceTexture);
when(resolutionFeature.getPreviewSize()).thenReturn(mockSize);
camera.startPreviewWithImageStream(mock(EventChannel.class));
@@ -887,7 +874,6 @@
Camera cameraSpy = spy(camera);
ArrayList<CaptureRequest.Builder> mockRequestBuilders = new ArrayList<>();
mockRequestBuilders.add(mock(CaptureRequest.Builder.class));
- SurfaceTexture mockSurfaceTexture = mock(SurfaceTexture.class);
Size mockSize = mock(Size.class);
MediaRecorder mockMediaRecorder = mock(MediaRecorder.class);
ImageReader mockPictureImageReader = mock(ImageReader.class);
@@ -898,10 +884,8 @@
cameraSpy.cameraDevice = fakeCamera;
MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
- TextureRegistry.SurfaceTextureEntry cameraFlutterTexture = cameraSpy.flutterTexture;
ResolutionFeature resolutionFeature = mockCameraFeatureFactory.mockResolutionFeature;
- when(cameraFlutterTexture.surfaceTexture()).thenReturn(mockSurfaceTexture);
when(resolutionFeature.getPreviewSize()).thenReturn(mockSize);
doNothing().when(cameraSpy).prepareRecording(mockResult);
@@ -1089,7 +1073,8 @@
camera.onConverged();
// A picture should be taken.
verify(mockCaptureSession, times(1)).capture(any(), any(), any());
- // The session shuold not be aborted as part of this flow, as this breaks capture on some
+ // The session shuold not be aborted as part of this flow, as this breaks
+ // capture on some
// devices, and causes delays on others.
verify(mockCaptureSession, never()).abortCaptures();
}
@@ -1097,19 +1082,14 @@
@Test
public void createCaptureSession_doesNotCloseCaptureSession() throws CameraAccessException {
Surface mockSurface = mock(Surface.class);
- SurfaceTexture mockSurfaceTexture = mock(SurfaceTexture.class);
- ResolutionFeature mockResolutionFeature = mock(ResolutionFeature.class);
Size mockSize = mock(Size.class);
ArrayList<CaptureRequest.Builder> mockRequestBuilders = new ArrayList<>();
mockRequestBuilders.add(mock(CaptureRequest.Builder.class));
CameraDeviceWrapper fakeCamera = new FakeCameraDeviceWrapper(mockRequestBuilders);
camera.cameraDevice = fakeCamera;
- TextureRegistry.SurfaceTextureEntry cameraFlutterTexture = camera.flutterTexture;
- CameraFeatures cameraFeatures = camera.cameraFeatures;
ResolutionFeature resolutionFeature = mockCameraFeatureFactory.mockResolutionFeature;
- when(cameraFlutterTexture.surfaceTexture()).thenReturn(mockSurfaceTexture);
when(resolutionFeature.getPreviewSize()).thenReturn(mockSize);
camera.createCaptureSession(CameraDevice.TEMPLATE_PREVIEW, mockSurface);
@@ -1122,8 +1102,6 @@
throws CameraAccessException {
Surface mockSurface = mock(Surface.class);
Surface mockSecondarySurface = mock(Surface.class);
- SurfaceTexture mockSurfaceTexture = mock(SurfaceTexture.class);
- ResolutionFeature mockResolutionFeature = mock(ResolutionFeature.class);
Size mockSize = mock(Size.class);
ArrayList<CaptureRequest.Builder> mockRequestBuilders = new ArrayList<>();
mockRequestBuilders.add(mock(CaptureRequest.Builder.class));
@@ -1133,11 +1111,8 @@
camera.pictureImageReader = mockPictureImageReader;
CaptureRequest.Builder mockPreviewRequestBuilder = mock(CaptureRequest.Builder.class);
- TextureRegistry.SurfaceTextureEntry cameraFlutterTexture = camera.flutterTexture;
- CameraFeatures cameraFeatures = camera.cameraFeatures;
ResolutionFeature resolutionFeature = mockCameraFeatureFactory.mockResolutionFeature;
- when(cameraFlutterTexture.surfaceTexture()).thenReturn(mockSurfaceTexture);
when(resolutionFeature.getPreviewSize()).thenReturn(mockSize);
when(fakeCamera.createCaptureRequest(anyInt())).thenReturn(mockPreviewRequestBuilder);
when(mockPictureImageReader.getSurface()).thenReturn(mockSurface);
@@ -1174,19 +1149,18 @@
@Test
public void startVideoRecording_shouldApplySettingsToMediaRecorder()
throws InterruptedException, IOException, CameraAccessException {
-
final Activity mockActivity = mock(Activity.class);
- final TextureRegistry.SurfaceTextureEntry mockFlutterTexture =
- mock(TextureRegistry.SurfaceTextureEntry.class);
+ final TextureRegistry.SurfaceProducer mockSurfaceProducer =
+ mock(TextureRegistry.SurfaceProducer.class);
final String cameraName = "1";
final ResolutionPreset resolutionPreset = ResolutionPreset.high;
final boolean enableAudio = true;
- //region These parameters should be set in android MediaRecorder.
+ // region These parameters should be set in android MediaRecorder.
final int fps = 15;
final int videoBitrate = 200000;
final int audioBitrate = 32000;
- //endregion
+ // endregion
when(mockCameraProperties.getCameraName()).thenReturn(cameraName);
@@ -1209,7 +1183,6 @@
try (final MockedStatic<File> mockFile = mockStatic(File.class);
final MockedConstruction<MediaRecorder> mockMediaRecorder =
Mockito.mockConstruction(MediaRecorder.class)) {
-
assertNotNull(mockMediaRecorder);
mockFile
@@ -1222,7 +1195,7 @@
spy(
new Camera(
mockActivity,
- mockFlutterTexture,
+ mockSurfaceProducer,
mockCameraFeatureFactory,
mockDartMessenger,
mockCameraProperties,
@@ -1255,19 +1228,15 @@
camera.cameraDevice = fakeCamera;
MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
- TextureRegistry.SurfaceTextureEntry cameraFlutterTexture = camera.flutterTexture;
-
ResolutionFeature resolutionFeature = mockCameraFeatureFactory.mockResolutionFeature;
- assertNotNull(cameraFlutterTexture);
- when(cameraFlutterTexture.surfaceTexture()).thenReturn(mockSurfaceTexture);
-
assertNotNull(resolutionFeature);
when(resolutionFeature.getPreviewSize()).thenReturn(mockSize);
camera.startVideoRecording(mockResult, null);
- //region Check that FPS parameter affects AE range at which the camera captures frames.
+ // region Check that FPS parameter affects AE range at which the camera captures
+ // frames.
assertEquals(camera.cameraFeatures.getFpsRange().getValue().getLower(), Integer.valueOf(fps));
assertEquals(camera.cameraFeatures.getFpsRange().getValue().getUpper(), Integer.valueOf(fps));
@@ -1276,15 +1245,15 @@
eq(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE),
argThat(
(Range<Integer> range) -> range.getLower() == fps && range.getUpper() == fps));
- //endregion
+ // endregion
final MediaRecorder recorder = camera.mediaRecorder;
- //region Check that parameters affects movies, written by MediaRecorder.
+ // region Check that parameters affects movies, written by MediaRecorder.
verify(recorder).setVideoFrameRate(fps);
verify(recorder).setAudioEncodingBitRate(audioBitrate);
verify(recorder).setVideoEncodingBitRate(videoBitrate);
- //endregion
+ // endregion
}
}
diff --git a/packages/camera/camera_android/android/src/test/java/io/flutter/plugins/camera/CameraTest_getRecordingProfileTest.java b/packages/camera/camera_android/android/src/test/java/io/flutter/plugins/camera/CameraTest_getRecordingProfileTest.java
index c5a97a1..8791ecd 100644
--- a/packages/camera/camera_android/android/src/test/java/io/flutter/plugins/camera/CameraTest_getRecordingProfileTest.java
+++ b/packages/camera/camera_android/android/src/test/java/io/flutter/plugins/camera/CameraTest_getRecordingProfileTest.java
@@ -60,15 +60,15 @@
mockDartMessenger = mock(DartMessenger.class);
final Activity mockActivity = mock(Activity.class);
- final TextureRegistry.SurfaceTextureEntry mockFlutterTexture =
- mock(TextureRegistry.SurfaceTextureEntry.class);
+ final TextureRegistry.SurfaceProducer mockSurfaceProducer =
+ mock(TextureRegistry.SurfaceProducer.class);
final ResolutionPreset resolutionPreset = ResolutionPreset.high;
final boolean enableAudio = false;
camera =
new Camera(
mockActivity,
- mockFlutterTexture,
+ mockSurfaceProducer,
mockCameraFeatureFactory,
mockDartMessenger,
mockCameraProperties,
diff --git a/packages/camera/camera_android/pubspec.yaml b/packages/camera/camera_android/pubspec.yaml
index 704f64b..f5b21d6 100644
--- a/packages/camera/camera_android/pubspec.yaml
+++ b/packages/camera/camera_android/pubspec.yaml
@@ -3,7 +3,7 @@
repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_android
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22
-version: 0.10.9+3
+version: 0.10.9+4
environment:
sdk: ^3.4.0