From 587408373b5e866404030f80908ce657e965254e Mon Sep 17 00:00:00 2001 From: BradenBagby Date: Mon, 15 May 2023 13:39:27 -0600 Subject: [PATCH 1/8] correctly disposes previous cameraId from device when switching between cameras, does not recreate _deviceOrientationSubscription each time --- packages/camera/camera/lib/src/camera_controller.dart | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/camera/camera/lib/src/camera_controller.dart b/packages/camera/camera/lib/src/camera_controller.dart index 69917d3f039..97b11f5bb60 100644 --- a/packages/camera/camera/lib/src/camera_controller.dart +++ b/packages/camera/camera/lib/src/camera_controller.dart @@ -294,11 +294,17 @@ class CameraController extends ValueNotifier { 'initialize was called on a disposed CameraController', ); } + + // dispose resources from previous camera description + if (await _initCalled ?? false) { + _unawaited(CameraPlatform.instance.dispose(_cameraId)); + } + try { final Completer initializeCompleter = Completer(); - _deviceOrientationSubscription = CameraPlatform.instance + _deviceOrientationSubscription ??= CameraPlatform.instance .onDeviceOrientationChanged() .listen((DeviceOrientationChangedEvent event) { value = value.copyWith( From adbb45c042f2ccfe74bb29684930e4eb7e422db0 Mon Sep 17 00:00:00 2001 From: BradenBagby Date: Mon, 15 May 2023 13:44:16 -0600 Subject: [PATCH 2/8] version and changelog --- packages/camera/camera/CHANGELOG.md | 4 ++++ packages/camera/camera/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md index b6dc896276e..e20a5b6e14a 100644 --- a/packages/camera/camera/CHANGELOG.md +++ b/packages/camera/camera/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.10.6 + +* Fixes camera resource handling + ## 0.10.5 * Adds NV21 as an image streaming option for Android. diff --git a/packages/camera/camera/pubspec.yaml b/packages/camera/camera/pubspec.yaml index 28648adbe69..0124fc57b13 100644 --- a/packages/camera/camera/pubspec.yaml +++ b/packages/camera/camera/pubspec.yaml @@ -4,7 +4,7 @@ description: A Flutter plugin for controlling the camera. Supports previewing Dart. repository: https://github.com/flutter/packages/tree/main/packages/camera/camera issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.10.5 +version: 0.10.6 environment: sdk: ">=2.18.0 <4.0.0" From 85de90bfd21f09ae8c65ef1c38062b19f41cad20 Mon Sep 17 00:00:00 2001 From: BradenBagby Date: Tue, 16 May 2023 09:23:29 -0600 Subject: [PATCH 3/8] fixes --- packages/camera/camera/lib/src/camera_controller.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/camera/camera/lib/src/camera_controller.dart b/packages/camera/camera/lib/src/camera_controller.dart index 97b11f5bb60..c8bbb08a592 100644 --- a/packages/camera/camera/lib/src/camera_controller.dart +++ b/packages/camera/camera/lib/src/camera_controller.dart @@ -296,7 +296,8 @@ class CameraController extends ValueNotifier { } // dispose resources from previous camera description - if (await _initCalled ?? false) { + if (_initCalled != null) { + await _initCalled; _unawaited(CameraPlatform.instance.dispose(_cameraId)); } From 51986e08965793a4cc8ad6a9601188f8f2d3e143 Mon Sep 17 00:00:00 2001 From: BradenBagby Date: Tue, 13 Jun 2023 15:18:02 -0600 Subject: [PATCH 4/8] moved to setDescription --- .../camera/camera/lib/src/camera_controller.dart | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/camera/camera/lib/src/camera_controller.dart b/packages/camera/camera/lib/src/camera_controller.dart index c8bbb08a592..d5a53721826 100644 --- a/packages/camera/camera/lib/src/camera_controller.dart +++ b/packages/camera/camera/lib/src/camera_controller.dart @@ -295,12 +295,6 @@ class CameraController extends ValueNotifier { ); } - // dispose resources from previous camera description - if (_initCalled != null) { - await _initCalled; - _unawaited(CameraPlatform.instance.dispose(_cameraId)); - } - try { final Completer initializeCompleter = Completer(); @@ -409,6 +403,12 @@ class CameraController extends ValueNotifier { await CameraPlatform.instance.setDescriptionWhileRecording(description); value = value.copyWith(description: description); } else { + // dispose resources from previous camera description + if (_initCalled != null) { + await _initCalled; + _unawaited(CameraPlatform.instance.dispose(_cameraId)); + } + await _initializeWithDescription(description); } } From 5c2a72a528b2327ecb280cc1eead53ac240b26c5 Mon Sep 17 00:00:00 2001 From: BradenBagby Date: Mon, 26 Jun 2023 18:59:30 -0600 Subject: [PATCH 5/8] awaits dispose --- packages/camera/camera/lib/src/camera_controller.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera/lib/src/camera_controller.dart b/packages/camera/camera/lib/src/camera_controller.dart index d5a53721826..9a3a3fe73e0 100644 --- a/packages/camera/camera/lib/src/camera_controller.dart +++ b/packages/camera/camera/lib/src/camera_controller.dart @@ -406,7 +406,7 @@ class CameraController extends ValueNotifier { // dispose resources from previous camera description if (_initCalled != null) { await _initCalled; - _unawaited(CameraPlatform.instance.dispose(_cameraId)); + await CameraPlatform.instance.dispose(_cameraId); } await _initializeWithDescription(description); From f85fcafbe73d22c0d71dc6784708eb39282ac8ae Mon Sep 17 00:00:00 2001 From: BradenBagby Date: Mon, 26 Jun 2023 19:01:14 -0600 Subject: [PATCH 6/8] fixes readme --- packages/camera/camera/CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md index e20a5b6e14a..4d319eeca83 100644 --- a/packages/camera/camera/CHANGELOG.md +++ b/packages/camera/camera/CHANGELOG.md @@ -1,5 +1,10 @@ ## 0.10.6 +- Fixes bug where old camera resources were not disposed when switching between camera descriptions +- Fixes bug where _deviceOrientationSubscription would be recreated every time the camera description was changed + +## 0.10.6 + * Fixes camera resource handling ## 0.10.5 From f2487fbf2cd54f6b0a09fe7b20bef35f93aa2d3e Mon Sep 17 00:00:00 2001 From: Braden Bagby <33461698+BradenBagby@users.noreply.github.com> Date: Mon, 10 Jul 2023 11:14:27 -0600 Subject: [PATCH 7/8] Update packages/camera/camera/CHANGELOG.md Co-authored-by: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> --- packages/camera/camera/CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md index 45d8139b9d5..afe8914541a 100644 --- a/packages/camera/camera/CHANGELOG.md +++ b/packages/camera/camera/CHANGELOG.md @@ -1,7 +1,7 @@ ## 0.10.6 -- Fixes bug where old camera resources were not disposed when switching between camera descriptions -- Fixes bug where _deviceOrientationSubscription was recreated every time the camera description was changed +* Fixes bug where old camera resources were not disposed when switching between camera descriptions. +* Fixes bug where _deviceOrientationSubscription was recreated every time the camera description was changed. ## 0.10.5+2 From 873e3bfad946eab819370a71ac5a551a631c64ad Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 22 Sep 2023 15:49:29 -0400 Subject: [PATCH 8/8] add a test --- .../camera/lib/src/camera_controller.dart | 21 ++++++----- packages/camera/camera/test/camera_test.dart | 36 +++++++++++++++++++ 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/packages/camera/camera/lib/src/camera_controller.dart b/packages/camera/camera/lib/src/camera_controller.dart index 15b6f906d34..2e8d0df8d74 100644 --- a/packages/camera/camera/lib/src/camera_controller.dart +++ b/packages/camera/camera/lib/src/camera_controller.dart @@ -265,7 +265,10 @@ class CameraController extends ValueNotifier { bool _isDisposed = false; StreamSubscription? _imageStreamSubscription; - FutureOr? _initCalled; + // A Future awaiting an attempt to initialize (e.g. after `initialize` was + // just called). If the controller has not been initialized at least once, + // this value is null. + Future? _initializeFuture; StreamSubscription? _deviceOrientationSubscription; @@ -295,6 +298,9 @@ class CameraController extends ValueNotifier { ); } + final Completer initializeCompleter = Completer(); + _initializeFuture = initializeCompleter.future; + try { final Completer initializeCompleter = Completer(); @@ -344,9 +350,9 @@ class CameraController extends ValueNotifier { ); } on PlatformException catch (e) { throw CameraException(e.code, e.message); + } finally { + initializeCompleter.complete(); } - - _initCalled = true; } /// Prepare the capture session for video recording. @@ -403,9 +409,8 @@ class CameraController extends ValueNotifier { await CameraPlatform.instance.setDescriptionWhileRecording(description); value = value.copyWith(description: description); } else { - // dispose resources from previous camera description - if (_initCalled != null) { - await _initCalled; + if (_initializeFuture != null) { + await _initializeFuture; await CameraPlatform.instance.dispose(_cameraId); } @@ -848,8 +853,8 @@ class CameraController extends ValueNotifier { _unawaited(_deviceOrientationSubscription?.cancel()); _isDisposed = true; super.dispose(); - if (_initCalled != null) { - await _initCalled; + if (_initializeFuture != null) { + await _initializeFuture; await CameraPlatform.instance.dispose(_cameraId); } } diff --git a/packages/camera/camera/test/camera_test.dart b/packages/camera/camera/test/camera_test.dart index ab8354f7ba0..ec111ed8594 100644 --- a/packages/camera/camera/test/camera_test.dart +++ b/packages/camera/camera/test/camera_test.dart @@ -192,6 +192,42 @@ void main() { .called(1); }); + test('setDescription waits for initialize before calling dispose', + () async { + final CameraController cameraController = CameraController( + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90, + ), + ResolutionPreset.max, + imageFormatGroup: ImageFormatGroup.bgra8888, + ); + + final Completer initializeCompleter = Completer(); + when(CameraPlatform.instance.initializeCamera( + mockInitializeCamera, + imageFormatGroup: ImageFormatGroup.bgra8888, + )).thenAnswer( + (_) => initializeCompleter.future, + ); + + unawaited(cameraController.initialize()); + + final Future setDescriptionFuture = cameraController.setDescription( + const CameraDescription( + name: 'cam2', + lensDirection: CameraLensDirection.front, + sensorOrientation: 90), + ); + verifyNever(CameraPlatform.instance.dispose(mockInitializeCamera)); + + initializeCompleter.complete(); + + await setDescriptionFuture; + verify(CameraPlatform.instance.dispose(mockInitializeCamera)); + }); + test('prepareForVideoRecording() calls $CameraPlatform ', () async { final CameraController cameraController = CameraController( const CameraDescription(