diff --git a/packages/camera/camera_platform_interface/CHANGELOG.md b/packages/camera/camera_platform_interface/CHANGELOG.md index e0736cac6a04..a68e94f1aa8a 100644 --- a/packages/camera/camera_platform_interface/CHANGELOG.md +++ b/packages/camera/camera_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.5.1 + +* Allows recorded video fps and bitrate control. + ## 2.5.0 * Adds NV21 as an image stream format (suitable for Android). diff --git a/packages/camera/camera_platform_interface/lib/camera_platform_interface.dart b/packages/camera/camera_platform_interface/lib/camera_platform_interface.dart index 6fab99b3d694..25fc417a9cc4 100644 --- a/packages/camera/camera_platform_interface/lib/camera_platform_interface.dart +++ b/packages/camera/camera_platform_interface/lib/camera_platform_interface.dart @@ -8,4 +8,5 @@ export 'package:cross_file/cross_file.dart'; export 'src/events/camera_event.dart'; export 'src/events/device_event.dart'; export 'src/platform_interface/camera_platform.dart'; +export 'src/types/media_settings.dart'; export 'src/types/types.dart'; diff --git a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart index 14d20fc817b2..fbd80bcb9a7d 100644 --- a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart +++ b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart @@ -84,19 +84,21 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future createCamera( + Future createCameraWithSettings( CameraDescription cameraDescription, - ResolutionPreset? resolutionPreset, { - bool enableAudio = false, - }) async { + MediaSettings? mediaSettings, + ) async { try { final Map? reply = await _channel .invokeMapMethod('create', { 'cameraName': cameraDescription.name, - 'resolutionPreset': resolutionPreset != null - ? _serializeResolutionPreset(resolutionPreset) + 'resolutionPreset': null != mediaSettings?.resolutionPreset + ? _serializeResolutionPreset(mediaSettings!.resolutionPreset!) : null, - 'enableAudio': enableAudio, + 'fps': mediaSettings?.fps, + 'videoBitrate': mediaSettings?.videoBitrate, + 'audioBitrate': mediaSettings?.audioBitrate, + 'enableAudio': mediaSettings?.enableAudio ?? false, }); return reply!['cameraId']! as int; diff --git a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart index b43629d4e0c3..b3bd4f7278aa 100644 --- a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart +++ b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart @@ -47,12 +47,26 @@ abstract class CameraPlatform extends PlatformInterface { } /// Creates an uninitialized camera instance and returns the cameraId. + /// Method will be deprecated. Use [createCameraWithSettings]. Future createCamera( CameraDescription cameraDescription, ResolutionPreset? resolutionPreset, { bool enableAudio = false, - }) { - throw UnimplementedError('createCamera() is not implemented.'); + }) => + createCameraWithSettings( + cameraDescription, + MediaSettings( + resolutionPreset: resolutionPreset, + enableAudio: enableAudio, + ), + ); + + /// Creates an uninitialized camera instance and returns the cameraId. + Future createCameraWithSettings( + CameraDescription cameraDescription, + MediaSettings? mediaSettings, + ) { + throw UnimplementedError('createCameraWithSettings() is not implemented.'); } /// Initializes the camera on the device. diff --git a/packages/camera/camera_platform_interface/lib/src/types/media_settings.dart b/packages/camera/camera_platform_interface/lib/src/types/media_settings.dart new file mode 100644 index 000000000000..8727b4e78728 --- /dev/null +++ b/packages/camera/camera_platform_interface/lib/src/types/media_settings.dart @@ -0,0 +1,57 @@ +// 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. + +// ignore_for_file: avoid_equals_and_hash_code_on_mutable_classes + +import 'resolution_preset.dart'; + +/// recording media settings. +class MediaSettings { + /// constructor + const MediaSettings({ + this.resolutionPreset, + this.fps, + this.videoBitrate, + this.audioBitrate, + this.enableAudio = false, + }); + + /// resolution preset + final ResolutionPreset? resolutionPreset; + + /// camera fps + final int? fps; + + /// recording video bitrate + final int? videoBitrate; + + /// recording audio bitrate + final int? audioBitrate; + + /// enable audio + final bool enableAudio; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is MediaSettings && + runtimeType == other.runtimeType && + resolutionPreset == other.resolutionPreset && + fps == other.fps && + videoBitrate == other.videoBitrate && + audioBitrate == other.audioBitrate && + enableAudio == other.enableAudio; + + @override + int get hashCode => + resolutionPreset.hashCode ^ + fps.hashCode ^ + videoBitrate.hashCode ^ + audioBitrate.hashCode ^ + enableAudio.hashCode; + + @override + String toString() => + 'MediaSettings{resolutionPreset: $resolutionPreset, fps: $fps, videoBitrate: $videoBitrate, audioBitrate: $audioBitrate, enableAudio: $enableAudio}'; +} diff --git a/packages/camera/camera_platform_interface/lib/src/types/types.dart b/packages/camera/camera_platform_interface/lib/src/types/types.dart index a8a4f8ca5dc4..f9a81559d680 100644 --- a/packages/camera/camera_platform_interface/lib/src/types/types.dart +++ b/packages/camera/camera_platform_interface/lib/src/types/types.dart @@ -9,5 +9,6 @@ export 'exposure_mode.dart'; export 'flash_mode.dart'; export 'focus_mode.dart'; export 'image_format_group.dart'; +export 'media_settings.dart'; export 'resolution_preset.dart'; export 'video_capture_options.dart'; diff --git a/packages/camera/camera_platform_interface/pubspec.yaml b/packages/camera/camera_platform_interface/pubspec.yaml index 7c3da2d4fc85..93b10fca0618 100644 --- a/packages/camera/camera_platform_interface/pubspec.yaml +++ b/packages/camera/camera_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ 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 # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 2.5.0 +version: 2.5.1 environment: sdk: ">=2.17.0 <4.0.0" diff --git a/packages/camera/camera_platform_interface/test/camera_platform_interface_test.dart b/packages/camera/camera_platform_interface/test/camera_platform_interface_test.dart index e3b6858e6d25..b3ea1d4e82c6 100644 --- a/packages/camera/camera_platform_interface/test/camera_platform_interface_test.dart +++ b/packages/camera/camera_platform_interface/test/camera_platform_interface_test.dart @@ -157,13 +157,19 @@ void main() { // Act & Assert expect( - () => cameraPlatform.createCamera( + () => cameraPlatform.createCameraWithSettings( const CameraDescription( name: 'back', lensDirection: CameraLensDirection.back, sensorOrientation: 0, ), - ResolutionPreset.high, + const MediaSettings( + resolutionPreset: ResolutionPreset.low, + fps: 15, + videoBitrate: 200000, + audioBitrate: 32000, + enableAudio: true, + ), ), throwsUnimplementedError, ); diff --git a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart index b01123d7cb29..c22cc18f66c8 100644 --- a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart +++ b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart @@ -33,12 +33,17 @@ void main() { final MethodChannelCamera camera = MethodChannelCamera(); // Act - final int cameraId = await camera.createCamera( + final int cameraId = await camera.createCameraWithSettings( const CameraDescription( name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0), - ResolutionPreset.high, + const MediaSettings( + resolutionPreset: ResolutionPreset.low, + fps: 15, + videoBitrate: 200000, + audioBitrate: 32000, + ), ); // Assert @@ -47,7 +52,10 @@ void main() { 'create', arguments: { 'cameraName': 'Test', - 'resolutionPreset': 'high', + 'resolutionPreset': 'low', + 'fps': 15, + 'videoBitrate': 200000, + 'audioBitrate': 32000, 'enableAudio': false }, ), @@ -71,13 +79,19 @@ void main() { // Act expect( - () => camera.createCamera( + () => camera.createCameraWithSettings( const CameraDescription( name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0, ), - ResolutionPreset.high, + const MediaSettings( + resolutionPreset: ResolutionPreset.low, + fps: 15, + videoBitrate: 200000, + audioBitrate: 32000, + enableAudio: true, + ), ), throwsA( isA() @@ -105,13 +119,19 @@ void main() { // Act expect( - () => camera.createCamera( + () => camera.createCameraWithSettings( const CameraDescription( name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0, ), - ResolutionPreset.high, + const MediaSettings( + resolutionPreset: ResolutionPreset.low, + fps: 15, + videoBitrate: 200000, + audioBitrate: 32000, + enableAudio: true, + ), ), throwsA( isA() @@ -167,13 +187,19 @@ void main() { 'initialize': null }); final MethodChannelCamera camera = MethodChannelCamera(); - final int cameraId = await camera.createCamera( + final int cameraId = await camera.createCameraWithSettings( const CameraDescription( name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0, ), - ResolutionPreset.high, + const MediaSettings( + resolutionPreset: ResolutionPreset.low, + fps: 15, + videoBitrate: 200000, + audioBitrate: 32000, + enableAudio: true, + ), ); // Act @@ -214,13 +240,19 @@ void main() { }); final MethodChannelCamera camera = MethodChannelCamera(); - final int cameraId = await camera.createCamera( + final int cameraId = await camera.createCameraWithSettings( const CameraDescription( name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0, ), - ResolutionPreset.high, + const MediaSettings( + resolutionPreset: ResolutionPreset.low, + fps: 15, + videoBitrate: 200000, + audioBitrate: 32000, + enableAudio: true, + ), ); final Future initializeFuture = camera.initializeCamera(cameraId); camera.cameraEventStreamController.add(CameraInitializedEvent( @@ -262,13 +294,19 @@ void main() { }, ); camera = MethodChannelCamera(); - cameraId = await camera.createCamera( + cameraId = await camera.createCameraWithSettings( const CameraDescription( name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0, ), - ResolutionPreset.high, + const MediaSettings( + resolutionPreset: ResolutionPreset.low, + fps: 15, + videoBitrate: 200000, + audioBitrate: 32000, + enableAudio: true, + ), ); final Future initializeFuture = camera.initializeCamera(cameraId); camera.cameraEventStreamController.add(CameraInitializedEvent( @@ -432,13 +470,19 @@ void main() { }, ); camera = MethodChannelCamera(); - cameraId = await camera.createCamera( + cameraId = await camera.createCameraWithSettings( const CameraDescription( name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0, ), - ResolutionPreset.high, + const MediaSettings( + resolutionPreset: ResolutionPreset.low, + fps: 15, + videoBitrate: 200000, + audioBitrate: 32000, + enableAudio: true, + ), ); final Future initializeFuture = camera.initializeCamera(cameraId); camera.cameraEventStreamController.add(