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

[camera] CameraPlatform.createCameraWithSettings #3615

Merged
merged 23 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
d3ec9b8
PR that has only the platform interface package changes from the #358…
PROGrand Sep 4, 2023
54e757a
touch
PROGrand Sep 4, 2023
197d67f
touch
PROGrand Sep 4, 2023
2a83a10
touch
PROGrand Sep 4, 2023
5dbb4e8
Update packages/camera/camera_platform_interface/pubspec.yaml
PROGrand Sep 19, 2023
3343cef
Update packages/camera/camera_platform_interface/CHANGELOG.md
PROGrand Sep 19, 2023
3a7db1a
Applied suggestions of https://github.com/flutter/packages/pull/3615#…
PROGrand Sep 21, 2023
40c4385
tested and analyzed
PROGrand Sep 21, 2023
442d25f
Delete packages/camera/camera_platform_interface/coverage/lcov.info
PROGrand Sep 24, 2023
462d032
Merge branch 'main' into camera-platform-interface
PROGrand Oct 12, 2023
3f3e092
delegated as in the "Note" section under (1) [here]( https://github.c…
PROGrand Oct 12, 2023
030d134
lexical corrections
PROGrand Oct 12, 2023
e8231d6
removed excessive comments
PROGrand Oct 12, 2023
a29e41b
correct description
PROGrand Oct 12, 2023
820f4b4
test all parameters combinations in operator ==
PROGrand Oct 12, 2023
26ac77d
Merge branch 'main' into camera-platform-interface
PROGrand Oct 12, 2023
d4d3c53
Merge branch 'main' into camera-platform-interface
PROGrand Oct 14, 2023
891dcca
Merge branch 'main' into camera-platform-interface
PROGrand Oct 18, 2023
afed7bc
tests are simplified
PROGrand Oct 18, 2023
bb01c48
Merge branch 'main' into camera-platform-interface
PROGrand Oct 18, 2023
a3a35a7
Merge branch 'main' into camera-platform-interface
PROGrand Oct 20, 2023
21967bc
Merge branch 'main' into camera-platform-interface
PROGrand Oct 23, 2023
7af349c
test: createCameraWithSettings() should call createCamera() using par…
PROGrand Oct 23, 2023
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
4 changes: 4 additions & 0 deletions packages/camera/camera_platform_interface/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.6.0

* Adds support to control video fps and bitrate. See `CameraPlatform.createCameraWithSettings`.

## 2.5.2

* Adds pub topics to package metadata.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,29 @@ class MethodChannelCamera extends CameraPlatform {
CameraDescription cameraDescription,
ResolutionPreset? resolutionPreset, {
bool enableAudio = false,
}) async {
}) async =>
createCameraWithSettings(
cameraDescription,
MediaSettings(
resolutionPreset: resolutionPreset, enableAudio: enableAudio));

@override
Future<int> createCameraWithSettings(
CameraDescription cameraDescription,
MediaSettings mediaSettings,
) async {
try {
final ResolutionPreset? resolutionPreset = mediaSettings.resolutionPreset;
final Map<String, dynamic>? reply = await _channel
.invokeMapMethod<String, dynamic>('create', <String, dynamic>{
'cameraName': cameraDescription.name,
'resolutionPreset': resolutionPreset != null
? _serializeResolutionPreset(resolutionPreset)
? _serializeResolutionPreset(mediaSettings.resolutionPreset!)
: null,
'enableAudio': enableAudio,
'fps': mediaSettings.fps,
'videoBitrate': mediaSettings.videoBitrate,
'audioBitrate': mediaSettings.audioBitrate,
'enableAudio': mediaSettings.enableAudio,
});

return reply!['cameraId']! as int;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,23 @@ abstract class CameraPlatform extends PlatformInterface {
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.
///
/// Pass MediaSettings() for defaults
Future<int> createCameraWithSettings(
CameraDescription cameraDescription,
MediaSettings mediaSettings,
) {
throw UnimplementedError('createCameraWithSettings() is not implemented.');
PROGrand marked this conversation as resolved.
Show resolved Hide resolved
}

/// Initializes the camera on the device.
Expand Down
PROGrand marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
PROGrand marked this conversation as resolved.
Show resolved Hide resolved
// 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.
///
/// Used in [CameraPlatform.createCameraWithSettings].
/// Allows to tune recorded video parameters, such as resolution, frame rate, bitrate.
/// If [fps], [videoBitrate] and [audioBitrate] passed, they must be greater than zero.
PROGrand marked this conversation as resolved.
Show resolved Hide resolved
class MediaSettings {
/// Creates a [MediaSettings].
const MediaSettings({
this.resolutionPreset,
this.fps,
this.videoBitrate,
this.audioBitrate,
this.enableAudio = false,
}) : assert(fps == null || fps > 0, 'fps must be null or greater than zero'),
assert(videoBitrate == null || videoBitrate > 0,
'videoBitrate must be null or greater than zero'),
assert(audioBitrate == null || audioBitrate > 0,
'audioBitrate must be null or greater than zero');

/// [ResolutionPreset] affect the quality of video recording and image capture.
final ResolutionPreset? resolutionPreset;

/// Rate at which frames should be captured by the camera in frames per second.
///
/// Must be null or greater than zero
PROGrand marked this conversation as resolved.
Show resolved Hide resolved
final int? fps;

/// The video encoding bit rate for recording.
///
/// Must be null or greater than zero
final int? videoBitrate;

/// The audio encoding bit rate for recording.
///
/// Must be null or greater than zero
final int? audioBitrate;
PROGrand marked this conversation as resolved.
Show resolved Hide resolved

/// Controls audio presence in recorded video.
final bool enableAudio;

@override
bool operator ==(Object other) {
if (identical(other, this)) {
return true;
}
if (other.runtimeType != runtimeType) {
return false;
}
return other is MediaSettings &&
resolutionPreset == other.resolutionPreset &&
fps == other.fps &&
videoBitrate == other.videoBitrate &&
audioBitrate == other.audioBitrate &&
enableAudio == other.enableAudio;
}

@override
int get hashCode => Object.hash(
resolutionPreset,
fps,
videoBitrate,
audioBitrate,
enableAudio,
);

@override
String toString() {
return 'MediaSettings{'
'resolutionPreset: $resolutionPreset, '
'fps: $fps, '
'videoBitrate: $videoBitrate, '
'audioBitrate: $audioBitrate, '
'enableAudio: $enableAudio}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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';
2 changes: 1 addition & 1 deletion packages/camera/camera_platform_interface/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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.2
version: 2.6.0

environment:
sdk: ">=2.19.0 <4.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,33 @@ void main() {
lensDirection: CameraLensDirection.back,
sensorOrientation: 0,
),
ResolutionPreset.high,
ResolutionPreset.low,
),
throwsUnimplementedError,
);
});

test(
'Default implementation of createCameraWithSettings() should throw unimplemented error',
PROGrand marked this conversation as resolved.
Show resolved Hide resolved
() {
// Arrange
final ExtendsCameraPlatform cameraPlatform = ExtendsCameraPlatform();

// Act & Assert
expect(
() => cameraPlatform.createCameraWithSettings(
const CameraDescription(
name: 'back',
lensDirection: CameraLensDirection.back,
sensorOrientation: 0,
),
const MediaSettings(
resolutionPreset: ResolutionPreset.low,
fps: 15,
videoBitrate: 200000,
audioBitrate: 32000,
enableAudio: true,
),
),
throwsUnimplementedError,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -47,7 +52,10 @@ void main() {
'create',
arguments: <String, Object?>{
'cameraName': 'Test',
'resolutionPreset': 'high',
'resolutionPreset': 'low',
'fps': 15,
'videoBitrate': 200000,
'audioBitrate': 32000,
'enableAudio': false
},
),
Expand All @@ -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<CameraException>()
Expand Down Expand Up @@ -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<CameraException>()
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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<void> initializeFuture = camera.initializeCamera(cameraId);
camera.cameraEventStreamController.add(CameraInitializedEvent(
Expand Down Expand Up @@ -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<void> initializeFuture = camera.initializeCamera(cameraId);
camera.cameraEventStreamController.add(CameraInitializedEvent(
Expand Down Expand Up @@ -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<void> initializeFuture = camera.initializeCamera(cameraId);
camera.cameraEventStreamController.add(
Expand Down
Loading