Repository navigation
[Camera] CameraController.takePicture() crashes due to Unconfigured Input/Output Surface #125314
Description
Is there an existing issue for this?
- I have searched the existing issues
- I have read the guide to filing a bug
Steps to reproduce
- Using the example code for Camera as inspiration, create a camera example app in Flutter
- Request the camera hardware info, using
cameras = await availableCameras(); - Create a camera controller, using something like this:
cameraController = CameraController( cameraDescription!, cameraResolutionPresetSelected, enableAudio: false, imageFormatGroup: imageFormatGroup, ); - Initialize the camera, using
await cameraController!.initialize(); - Observe camera preview working as intended
- Attempt to take a picture by calling the Camera plugin's
cameraController.takePicture() - A crash stops the application with this stacktrace:
E/AndroidRuntime(25340): Process: com.disney.mobile_chassis_camera.mobile_chassis_camera_example, PID: 25340 E/AndroidRuntime(25340): java.lang.IllegalArgumentException: CaptureRequest contains unconfigured Input/Output Surface! E/AndroidRuntime(25340): at android.hardware.camera2.CaptureRequest.convertSurfaceToStreamId(CaptureRequest.java:765) E/AndroidRuntime(25340): at android.hardware.camera2.impl.CameraDeviceImpl.submitCaptureRequest(CameraDeviceImpl.java:1289) E/AndroidRuntime(25340): at android.hardware.camera2.impl.CameraDeviceImpl.capture(CameraDeviceImpl.java:1126) E/AndroidRuntime(25340): at android.hardware.camera2.impl.CameraCaptureSessionImpl.capture(CameraCaptureSessionImpl.java:189) E/AndroidRuntime(25340): at io.flutter.plugins.camera.Camera.takePictureAfterPrecapture(Camera.java:663) E/AndroidRuntime(25340): at io.flutter.plugins.camera.Camera.onConverged(Camera.java:225) E/AndroidRuntime(25340): at io.flutter.plugins.camera.CameraCaptureCallback.process(CameraCaptureCallback.java:135) E/AndroidRuntime(25340): at io.flutter.plugins.camera.CameraCaptureCallback.onCaptureProgressed(CameraCaptureCallback.java:161) E/AndroidRuntime(25340): at android.hardware.camera2.impl.CameraCaptureSessionImpl$1.lambda$onCaptureProgressed$2$android-hardware-camera2-impl-CameraCaptureSessionImpl$1(CameraCaptureSessionImpl.java:679) E/AndroidRuntime(25340): at android.hardware.camera2.impl.CameraCaptureSessionImpl$1$$ExternalSyntheticLambda0.run(Unknown Source:8) E/AndroidRuntime(25340): at android.os.Handler.handleCallback(Handler.java:942) E/AndroidRuntime(25340): at android.os.Handler.dispatchMessage(Handler.java:99) E/AndroidRuntime(25340): at android.os.Looper.loopOnce(Looper.java:226) E/AndroidRuntime(25340): at android.os.Looper.loop(Looper.java:313) E/AndroidRuntime(25340): at android.os.HandlerThread.run(HandlerThread.java:67) I/flutter (25340): mobile_chassis_camera - AppLifecycleState: AppLifecycleState.inactive I/flutter (25340): mobile_chassis_camera - onDidChangeAppLifecycleState - state: AppLifecycleState.inactive I/flutter (25340): mobile_chassis_camera - dismiss I/Process (25340): Sending signal. PID: 25340 SIG: 9 Lost connection to device.
The issue we experienced seems similar to this open bug:
#46082
Tested with a Galaxy S21 Ultra 5G (Android 13) device, using Camera version ^0.10.4
Expected results
CameraController.takePhoto() should work when it has been configured for our use.
Actual results
We cannot use or properly configure the Camera to take a photo.
Code sample
Use the official example, then attempt to take a photo.
Screenshots or Video
Screenshots / Video demonstration
[Upload media here]
Logs
Logs
I/flutter (25340): mobile_chassis_camera - capturePhoto
I/flutter (25340): mobile_chassis_camera - capturePhoto - attempting cameraController.takePicture(). Camera controller: CameraController#c03c2(CameraValue(isRecordingVideo: false, isInitialized: true, errorDescription: null, previewSize: Size(1280.0, 720.0), isStreamingImages: true, flashMode: FlashMode.auto, exposureMode: ExposureMode.auto, focusMode: FocusMode.auto, exposurePointSupported: true, focusPointSupported: true, deviceOrientation: DeviceOrientation.portraitUp, lockedCaptureOrientation: null, recordingOrientation: null, isPreviewPaused: false, previewPausedOrientation: null, description: CameraDescription(0, CameraLensDirection.back, 90)))
I/flutter (25340): mobile_chassis_camera - onImageStreamPauseOrResume - should resume: false
I/Camera (25340): startPreview
I/CameraManagerGlobal(25340): Camera 0 facing CAMERA_FACING_BACK state now CAMERA_STATE_IDLE for client com.disney.mobile_chassis_camera.mobile_chassis_camera_example API Level 2
I/Camera (25340): CameraCaptureSession onConfigured
I/Camera (25340): Updating builder settings
W/_camera_example(25340): Long monitor contention with owner main (25340) at void android.hardware.camera2.impl.CameraDeviceImpl.waitUntilIdle()(CameraDeviceImpl.java:1402) waiters=0 in void android.hardware.camera2.impl.CameraDeviceImpl$4.run() for 428ms
...
W/_camera_example(25340): Long monitor contention with owner main (25340) at void android.hardware.camera2.impl.CameraDeviceImpl.waitUntilIdle()(CameraDeviceImpl.java:1402) waiters=1 in void android.hardware.camera2.impl.CameraDeviceImpl$CameraDeviceCallbacks.onResultReceived(android.hardware.camera2.impl.CameraMetadataNative, android.hardware.camera2.impl.CaptureResultExtras, android.hardware.camera2.impl.PhysicalCaptureResultInfo[]) for 429ms
I/Camera (25340): runPictureAutoFocus
I/Camera (25340): lockAutoFocus
I/CameraManagerGlobal(25340): Camera 0 facing CAMERA_FACING_BACK state now CAMERA_STATE_ACTIVE for client com.disney.mobile_chassis_camera.mobile_chassis_camera_example API Level 2
D/CameraCaptureCallback(25340): CameraCaptureCallback | state: STATE_WAITING_FOCUS | afState: 2 | aeState: 2
D/CameraCaptureCallback(25340): CameraCaptureCallback | state: STATE_WAITING_FOCUS | afState: 2 | aeState: 2
D/CameraCaptureCallback(25340): CameraCaptureCallback | state: STATE_WAITING_FOCUS | afState: 2 | aeState: 2
D/CameraCaptureCallback(25340): CameraCaptureCallback | state: STATE_WAITING_FOCUS | afState: 2 | aeState: 2
D/CameraCaptureCallback(25340): CameraCaptureCallback | state: STATE_WAITING_FOCUS | afState: 2 | aeState: 2
D/CameraCaptureCallback(25340): CameraCaptureCallback | state: STATE_WAITING_FOCUS | afState: 2 | aeState: 2
D/CameraCaptureCallback(25340): CameraCaptureCallback | state: STATE_WAITING_FOCUS | afState: 2 | aeState: 2
D/CameraCaptureCallback(25340): CameraCaptureCallback | state: STATE_WAITING_FOCUS | afState: 2 | aeState: 2
D/CameraCaptureCallback(25340): CameraCaptureCallback | state: STATE_WAITING_FOCUS | afState: 2 | aeState: 2
D/CameraCaptureCallback(25340): CameraCaptureCallback | state: STATE_WAITING_FOCUS | afState: 2 | aeState: 2
D/CameraCaptureCallback(25340): CameraCaptureCallback | state: STATE_WAITING_FOCUS | afState: 2 | aeState: 2
I/Camera (25340): CameraCaptureSession onClosed
W/System (25340): A resource failed to call Surface.release.
I/CameraManagerGlobal(25340): Camera 0 facing CAMERA_FACING_BACK state now CAMERA_STATE_IDLE for client com.disney.mobile_chassis_camera.mobile_chassis_camera_example API Level 2
I/ViewRootImpl@c137711[MainActivity](25340): ViewPostIme pointer 0
I/ViewRootImpl@c137711[MainActivity](25340): ViewPostIme pointer 1
I/flutter (25340): mobile_chassis_camera - onCameraPreviewToggle toggled: true
I/flutter (25340): mobile_chassis_camera - onImageStreamPauseOrResume - should resume: true
I/Camera (25340): CameraCaptureSession onClosed
I/Camera (25340): startPreviewWithImageStream
I/Camera (25340): CameraCaptureSession onConfigured
I/Camera (25340): Updating builder settings
D/Camera (25340): Updating builder with feature: ExposureLockFeature
D/Camera (25340): Updating builder with feature: ExposurePointFeature
D/Camera (25340): Updating builder with feature: ZoomLevelFeature
I/Camera (25340): refreshPreviewCaptureSession
D/Camera (25340): Updating builder with feature: AutoFocusFeature
W/_camera_example(25340): Long monitor contention with owner main (25340) at void android.hardware.camera2.impl.CameraDeviceImpl.waitUntilIdle()(CameraDeviceImpl.java:1402) waiters=0 in void android.hardware.camera2.impl.CameraDeviceImpl$4.run() for 282ms
D/Camera (25340): Updating builder with feature: NoiseReductionFeature
I/Camera (25340): updateNoiseReduction | currentSetting: fast
D/Camera (25340): Updating builder with feature: FocusPointFeature
D/Camera (25340): Updating builder with feature: ResolutionFeature
D/Camera (25340): Updating builder with feature: SensorOrientationFeature
D/Camera (25340): Updating builder with feature: FlashFeature
D/Camera (25340): Updating builder with feature: ExposureOffsetFeature
D/Camera (25340): Updating builder with feature: FpsRangeFeature
I/Camera (25340): refreshPreviewCaptureSession
I/CameraManagerGlobal(25340): Camera 0 facing CAMERA_FACING_BACK state now CAMERA_STATE_ACTIVE for client com.disney.mobile_chassis_camera.mobile_chassis_camera_example API Level 2
D/CameraCaptureCallback(25340): CameraCaptureCallback | state: STATE_WAITING_FOCUS | afState: 2 | aeState: 1
W/CameraCaptureCallback(25340): Focus timeout, moving on with capture
I/Camera (25340): runPrecaptureSequence
I/Camera (25340): refreshPreviewCaptureSession
D/CameraCaptureCallback(25340): CameraCaptureCallback | state: STATE_WAITING_PRECAPTURE_START | afState: 2 | aeState: 1
W/CameraCaptureCallback(25340): Metering timeout waiting for pre-capture to start, moving on with capture
D/CameraCaptureCallback(25340): CameraCaptureCallback | state: STATE_WAITING_PRECAPTURE_DONE | afState: 2 | aeState: 1
I/Camera (25340): captureStillPicture
D/Camera (25340): Updating builder with feature: ExposureLockFeature
D/Camera (25340): Updating builder with feature: ExposurePointFeature
D/Camera (25340): Updating builder with feature: ZoomLevelFeature
D/Camera (25340): Updating builder with feature: AutoFocusFeature
D/Camera (25340): Updating builder with feature: NoiseReductionFeature
I/Camera (25340): updateNoiseReduction | currentSetting: fast
D/Camera (25340): Updating builder with feature: FocusPointFeature
D/Camera (25340): Updating builder with feature: ResolutionFeature
D/Camera (25340): Updating builder with feature: SensorOrientationFeature
D/Camera (25340): Updating builder with feature: FlashFeature
D/Camera (25340): Updating builder with feature: ExposureOffsetFeature
D/Camera (25340): Updating builder with feature: FpsRangeFeature
I/Camera (25340): sending capture request
E/AndroidRuntime(25340): FATAL EXCEPTION: CameraBackground
E/AndroidRuntime(25340): Process: com.disney.mobile_chassis_camera.mobile_chassis_camera_example, PID: 25340
E/AndroidRuntime(25340): java.lang.IllegalArgumentException: CaptureRequest contains unconfigured Input/Output Surface!
E/AndroidRuntime(25340): at android.hardware.camera2.CaptureRequest.convertSurfaceToStreamId(CaptureRequest.java:765)
E/AndroidRuntime(25340): at android.hardware.camera2.impl.CameraDeviceImpl.submitCaptureRequest(CameraDeviceImpl.java:1289)
E/AndroidRuntime(25340): at android.hardware.camera2.impl.CameraDeviceImpl.capture(CameraDeviceImpl.java:1126)
E/AndroidRuntime(25340): at android.hardware.camera2.impl.CameraCaptureSessionImpl.capture(CameraCaptureSessionImpl.java:189)
E/AndroidRuntime(25340): at io.flutter.plugins.camera.Camera.takePictureAfterPrecapture(Camera.java:663)
E/AndroidRuntime(25340): at io.flutter.plugins.camera.Camera.onConverged(Camera.java:225)
E/AndroidRuntime(25340): at io.flutter.plugins.camera.CameraCaptureCallback.process(CameraCaptureCallback.java:135)
E/AndroidRuntime(25340): at io.flutter.plugins.camera.CameraCaptureCallback.onCaptureProgressed(CameraCaptureCallback.java:161)
E/AndroidRuntime(25340): at android.hardware.camera2.impl.CameraCaptureSessionImpl$1.lambda$onCaptureProgressed$2$android-hardware-camera2-impl-CameraCaptureSessionImpl$1(CameraCaptureSessionImpl.java:679)
E/AndroidRuntime(25340): at android.hardware.camera2.impl.CameraCaptureSessionImpl$1$$ExternalSyntheticLambda0.run(Unknown Source:8)
E/AndroidRuntime(25340): at android.os.Handler.handleCallback(Handler.java:942)
E/AndroidRuntime(25340): at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(25340): at android.os.Looper.loopOnce(Looper.java:226)
E/AndroidRuntime(25340): at android.os.Looper.loop(Looper.java:313)
E/AndroidRuntime(25340): at android.os.HandlerThread.run(HandlerThread.java:67)
I/flutter (25340): mobile_chassis_camera - AppLifecycleState: AppLifecycleState.inactive
I/flutter (25340): mobile_chassis_camera - onDidChangeAppLifecycleState - state: AppLifecycleState.inactive
I/flutter (25340): mobile_chassis_camera - dismiss
I/Process (25340): Sending signal. PID: 25340 SIG: 9
Lost connection to device.Flutter Doctor output
Doctor output
[✓] Flutter (Channel stable, 3.7.11, on macOS 12.6.4 21G526 darwin-x64, locale en-US)
• Flutter version 3.7.11 on channel stable at /Users/Tyson.Miller/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision f72efea43c (10 days ago), 2023-04-11 11:57:21 -0700
• Engine revision 1a65d409c7
• Dart version 2.19.6
• DevTools version 2.20.1
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.1)
• Android SDK at /Users/Tyson.Miller/Library/Android/sdk
• Platform android-33, build-tools 33.0.1
• ANDROID_HOME = /Users/Tyson.Miller/Library/Android/sdk
• ANDROID_SDK_ROOT = /Users/Tyson.Miller/Library/Android/sdk
• Java binary at: /Users/Tyson.Miller/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/213.7172.25.2113.9123335/Android
Studio.app/Contents/jre/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 14.2)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 14C18
• CocoaPods version 1.12.1
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 2021.3)
• Android Studio at /Users/Tyson.Miller/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/213.7172.25.2113.9123335/Android
Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)
[✓] Android Studio (version 2021.1)
• Android Studio at /Users/Tyson.Miller/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/211.7628.21.2111.8309675/Android
Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7590822)
[✓] IntelliJ IDEA Community Edition (version 2022.3.1)
• IntelliJ at /Users/Tyson.Miller/Library/Application Support/JetBrains/Toolbox/apps/IDEA-C/ch-0/223.8214.52/IntelliJ IDEA CE.app
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
[✓] IntelliJ IDEA Community Edition (version 2022.3)
• IntelliJ at /Users/Tyson.Miller/Library/Application Support/JetBrains/Toolbox/apps/IDEA-C/ch-0/223.7571.182/IntelliJ IDEA CE.app
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
[✓] VS Code (version 1.76.2)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.62.0
[✓] Connected device (1 available)
• Chrome (web) • chrome • web-javascript • Google Chrome 112.0.5615.137
[✓] HTTP Host Availability
• All required HTTP hosts are available
• No issues found!
Activity
[-][Camera] CameraController.takePicture() crashes due to missing Input/Output Surface[/-][+][Camera] CameraController.takePicture() crashes due to Unconfigured Input/Output Surface[/+]camsim99 commentedon Apr 21, 2023
To reproduce this issue, I created a fresh Flutter app, copied the example app into my
main.dartfile, but changed my app to have a button to take a picture:I ran this on a Pixel 3 running Android 12 with
cameraversion ^0.10.4, and it seems to work as expected.@MILLT189 are there any steps I'm missing in terms of reproducing the error you got? The similar issue you linked seems to also involve image streaming, so I'm wondering if you may be using that. Otherwise, I'm guessing this may be a device-specific or Android version specific issue.
MILLT189 commentedon Apr 21, 2023
@camsim99 my example app is using creating a CameraPreview (from Camera pub.dev) and starting a stream to use with MLKit barcode model.
If you're not seeing issues with Android 12, I think it may be limited to devices running Android 13 (like my Galaxy S21 Ultra 5G)
Source for camera preview init: https://pub.dev/packages/camera/example
MILLT189 commentedon Apr 21, 2023
As far as emulators are concerned, Pixel 4 with SDK 32 doesn't seem to throw any fatal errors when photo capture is attempted.
When I run a Pixel 4 emulator with SDK 33, I'll get this error:
camsim99 commentedon Apr 21, 2023
I modified my app to start image streaming before taking the photo, and I was able to reproduce this issue. So, it does seem related to #46082 (comment), as it seems to be caused by the combination of displaying a live preview, starting and image stream, and then taking a picture.
camsim99 commentedon Apr 24, 2023
At least part of the issue seems to be coming from the fact that the surface currently needed for image capture (retrieved from
ImageReader#getSurface()) as seen here, is not part of the most recent call to create aCameraCaptureSession, as the most recent call is used to configure image streaming, as seen here. This is a requirement forCaptureRequest.Builder#addTarget(Surface)as per the docs.So, it seems like fixing this issue is a matter of properly configuring surfaces needed for image streaming and preview, as well as their respective
ImageReaders.MILLT189 commentedon Jun 12, 2023
Is there an ETA for this??
This crash is a blocker for my team and we need to be able to use the camera in order for us to use Flutter as a platform.
camsim99 commentedon Jun 14, 2023
I'm picking back up work on this today, sorry for the delay. Will update here with status updates as soon as I can!
camsim99 commentedon Jun 16, 2023
Status update: Seems like the comment I left above is the crux of the issue, but there is another issue concerning how we configure
ImageReaders to pick up available images. At a high level, right now, we are configuring image capture essentially the same as image streaming, which is causing errors related to the listener used to receive the captured image. That listener is receiving multiple images because it is configured like image streaming and conflicting with the behavior of image streaming itself. Working on fixing this issue.magraesser-disney commentedon Jun 22, 2023
Checking in for status on this issue.
AresVampire commentedon Jun 22, 2023
You must call
stopImageStreamfirst before taking photo with camera to avoid crash.camsim99 commentedon Jun 23, 2023
I have been out most of this week, apologies for the late update. I will return to hopefully finish solving the issue next week, but here is what I've found:
Using multiple
ImageReaders seems to be okay, but we will have to make sure we only save the image that matches the image that was captured. This involves adding images acquired/captured during a still capture to a queue that the still captureImageReadercan access and then use to match images it receives to the one captured image using image format and timestamp. It should look something closer to the camera2 example: https://github.com/android/camera-samples/blob/cce92313279754d08a77ee6c35ad8126e25e9245/Camera2Basic/app/src/main/java/com/example/android/camera2/basic/fragments/CameraFragment.kt#L322C9-L322C9.The tricky part is the fact that we don't know if the capture will finish first or the
ImageReaderwill get access to a new image first. The camera2 example seems to assume an order (capture completes first), but this does not seem guaranteed by my own testing and a quick search. Will follow up on this to figure out the best way to proceed.camsim99 commentedon Jun 27, 2023
I was able to get still capture working with the queue/timestamp method, but like I mentioned above, it's harder when image streaming becomes involved because images will become available before the capture completes, so we end up acquiring > the max number of images we can at a time before closing them (as we add them to a queue and wait to check their timestamps). I am going to follow up today with folks more knowledgable on camera2 on whether or not there is a way to ensure the still capture
ImageReaderreceives only one image as a result of the capture and if not, discuss strategies to best handle this timing issue.camsim99 commentedon Jun 27, 2023
It turns out that receiving multiple images was a result of using the surface of the JPEG
ImageReader(the one for still capture) being set as a target of the request builder used for displaying a live preview, and using it to set a repeating request. Taking out thatImageReader's surface solves that issue. I already fixed the original issue by adding its surface to the capture session used for image streaming, so I will start on a PR for the fix.[camera_android] Support concurrently image capture and image streami…
github-actions commentedon Jul 14, 2023
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.[camera_android] Support concurrently image capture and image streami…
[camera_android] Support concurrently image capture and image streami…