mirror of
https://github.com/flutter/packages.git
synced 2025-07-03 17:18:22 +08:00
[camera] CameraPlatform.createCameraWithSettings (#3615)
## Platform interface of federated plugin This is the `platform-interface` part of `camera` PR #3586. ## App-facing change Previously, CameraController was unable to setup fps and bitrates, allowing only resolution settings like this: ```dart controller = CameraController(_cameras[0], ResolutionPreset.max); ``` This PR gives additional functionality to set `fps` and `bitrates` via `withSettings`: ```dart controller = CameraController.withSettings( _cameras[0], mediaSettings: const MediaSettings( resolutionPreset: ResolutionPreset.low, fps: 15, videoBitrate: 200000, audioBitrate: 32000, enableAudio: true, ), ); ``` ## Android, iOS, etc. All platforms must implement `CameraPlatform.createCameraWithSettings` in addition to `CameraPlatform.createCamera`, providing platform specific code for `fps` and `bitrate' platform: ```dart Future<int> createCamera( CameraDescription cameraDescription, CameraDescription cameraDescription, ResolutionPreset? resolutionPreset, { ResolutionPreset? resolutionPreset, { bool enableAudio = false, 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<int> createCameraWithSettings( CameraDescription cameraDescription, MediaSettings? mediaSettings, ) { throw UnimplementedError('createCameraWithSettings() is not implemented.'); } } ```
This commit is contained in:

committed by
GitHub

parent
a2d8672340
commit
4bf51144c2
@ -1,3 +1,7 @@
|
|||||||
|
## 2.6.0
|
||||||
|
|
||||||
|
* Adds support to control video fps and bitrate. See `CameraPlatform.createCameraWithSettings`.
|
||||||
|
|
||||||
## 2.5.2
|
## 2.5.2
|
||||||
|
|
||||||
* Adds pub topics to package metadata.
|
* Adds pub topics to package metadata.
|
||||||
|
@ -8,4 +8,5 @@ export 'package:cross_file/cross_file.dart';
|
|||||||
export 'src/events/camera_event.dart';
|
export 'src/events/camera_event.dart';
|
||||||
export 'src/events/device_event.dart';
|
export 'src/events/device_event.dart';
|
||||||
export 'src/platform_interface/camera_platform.dart';
|
export 'src/platform_interface/camera_platform.dart';
|
||||||
|
export 'src/types/media_settings.dart';
|
||||||
export 'src/types/types.dart';
|
export 'src/types/types.dart';
|
||||||
|
@ -88,15 +88,29 @@ class MethodChannelCamera extends CameraPlatform {
|
|||||||
CameraDescription cameraDescription,
|
CameraDescription cameraDescription,
|
||||||
ResolutionPreset? resolutionPreset, {
|
ResolutionPreset? resolutionPreset, {
|
||||||
bool enableAudio = false,
|
bool enableAudio = false,
|
||||||
}) async {
|
}) async =>
|
||||||
|
createCameraWithSettings(
|
||||||
|
cameraDescription,
|
||||||
|
MediaSettings(
|
||||||
|
resolutionPreset: resolutionPreset, enableAudio: enableAudio));
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<int> createCameraWithSettings(
|
||||||
|
CameraDescription cameraDescription,
|
||||||
|
MediaSettings mediaSettings,
|
||||||
|
) async {
|
||||||
try {
|
try {
|
||||||
|
final ResolutionPreset? resolutionPreset = mediaSettings.resolutionPreset;
|
||||||
final Map<String, dynamic>? reply = await _channel
|
final Map<String, dynamic>? reply = await _channel
|
||||||
.invokeMapMethod<String, dynamic>('create', <String, dynamic>{
|
.invokeMapMethod<String, dynamic>('create', <String, dynamic>{
|
||||||
'cameraName': cameraDescription.name,
|
'cameraName': cameraDescription.name,
|
||||||
'resolutionPreset': resolutionPreset != null
|
'resolutionPreset': resolutionPreset != null
|
||||||
? _serializeResolutionPreset(resolutionPreset)
|
? _serializeResolutionPreset(mediaSettings.resolutionPreset!)
|
||||||
: null,
|
: null,
|
||||||
'enableAudio': enableAudio,
|
'fps': mediaSettings.fps,
|
||||||
|
'videoBitrate': mediaSettings.videoBitrate,
|
||||||
|
'audioBitrate': mediaSettings.audioBitrate,
|
||||||
|
'enableAudio': mediaSettings.enableAudio,
|
||||||
});
|
});
|
||||||
|
|
||||||
return reply!['cameraId']! as int;
|
return reply!['cameraId']! as int;
|
||||||
|
@ -55,6 +55,20 @@ abstract class CameraPlatform extends PlatformInterface {
|
|||||||
throw UnimplementedError('createCamera() is not implemented.');
|
throw UnimplementedError('createCamera() is not implemented.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates an uninitialized camera instance and returns the cameraId.
|
||||||
|
///
|
||||||
|
/// Pass MediaSettings() for defaults
|
||||||
|
Future<int> createCameraWithSettings(
|
||||||
|
CameraDescription cameraDescription,
|
||||||
|
MediaSettings mediaSettings,
|
||||||
|
) {
|
||||||
|
return createCamera(
|
||||||
|
cameraDescription,
|
||||||
|
mediaSettings.resolutionPreset,
|
||||||
|
enableAudio: mediaSettings.enableAudio,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Initializes the camera on the device.
|
/// Initializes the camera on the device.
|
||||||
///
|
///
|
||||||
/// [imageFormatGroup] is used to specify the image formatting used.
|
/// [imageFormatGroup] is used to specify the image formatting used.
|
||||||
|
@ -0,0 +1,77 @@
|
|||||||
|
// 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.
|
||||||
|
///
|
||||||
|
/// Used in [CameraPlatform.createCameraWithSettings].
|
||||||
|
/// Allows to tune recorded video parameters, such as resolution, frame rate, bitrate.
|
||||||
|
/// If [fps], [videoBitrate] or [audioBitrate] are passed, they must be greater than zero.
|
||||||
|
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.
|
||||||
|
final int? fps;
|
||||||
|
|
||||||
|
/// The video encoding bit rate for recording.
|
||||||
|
final int? videoBitrate;
|
||||||
|
|
||||||
|
/// The audio encoding bit rate for recording.
|
||||||
|
final int? audioBitrate;
|
||||||
|
|
||||||
|
/// 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}';
|
||||||
|
}
|
||||||
|
}
|
@ -9,5 +9,6 @@ export 'exposure_mode.dart';
|
|||||||
export 'flash_mode.dart';
|
export 'flash_mode.dart';
|
||||||
export 'focus_mode.dart';
|
export 'focus_mode.dart';
|
||||||
export 'image_format_group.dart';
|
export 'image_format_group.dart';
|
||||||
|
export 'media_settings.dart';
|
||||||
export 'resolution_preset.dart';
|
export 'resolution_preset.dart';
|
||||||
export 'video_capture_options.dart';
|
export 'video_capture_options.dart';
|
||||||
|
@ -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
|
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
|
# 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
|
# less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
|
||||||
version: 2.5.2
|
version: 2.6.0
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.19.0 <4.0.0"
|
sdk: ">=2.19.0 <4.0.0"
|
||||||
|
@ -163,12 +163,67 @@ void main() {
|
|||||||
lensDirection: CameraLensDirection.back,
|
lensDirection: CameraLensDirection.back,
|
||||||
sensorOrientation: 0,
|
sensorOrientation: 0,
|
||||||
),
|
),
|
||||||
ResolutionPreset.high,
|
ResolutionPreset.low,
|
||||||
),
|
),
|
||||||
throwsUnimplementedError,
|
throwsUnimplementedError,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'Default implementation of createCameraWithSettings() should call createCamera() passing parameters',
|
||||||
|
() {
|
||||||
|
// Arrange
|
||||||
|
const CameraDescription cameraDescription = CameraDescription(
|
||||||
|
name: 'back',
|
||||||
|
lensDirection: CameraLensDirection.back,
|
||||||
|
sensorOrientation: 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
const MediaSettings mediaSettings = MediaSettings(
|
||||||
|
resolutionPreset: ResolutionPreset.low,
|
||||||
|
fps: 15,
|
||||||
|
videoBitrate: 200000,
|
||||||
|
audioBitrate: 32000,
|
||||||
|
enableAudio: true,
|
||||||
|
);
|
||||||
|
|
||||||
|
bool createCameraCalled = false;
|
||||||
|
|
||||||
|
final OverriddenCameraPlatform cameraPlatform = OverriddenCameraPlatform((
|
||||||
|
CameraDescription cameraDescriptionArg,
|
||||||
|
ResolutionPreset? resolutionPresetArg,
|
||||||
|
bool enableAudioArg,
|
||||||
|
) {
|
||||||
|
expect(
|
||||||
|
cameraDescriptionArg,
|
||||||
|
cameraDescription,
|
||||||
|
reason: 'should pass camera description',
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
resolutionPresetArg,
|
||||||
|
mediaSettings.resolutionPreset,
|
||||||
|
reason: 'should pass resolution preset',
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
enableAudioArg,
|
||||||
|
mediaSettings.enableAudio,
|
||||||
|
reason: 'should pass enableAudio',
|
||||||
|
);
|
||||||
|
|
||||||
|
createCameraCalled = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
cameraPlatform.createCameraWithSettings(
|
||||||
|
cameraDescription,
|
||||||
|
mediaSettings,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(createCameraCalled, isTrue,
|
||||||
|
reason:
|
||||||
|
'default implementation of createCameraWithSettings should call createCamera passing parameters');
|
||||||
|
});
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'Default implementation of initializeCamera() should throw unimplemented error',
|
'Default implementation of initializeCamera() should throw unimplemented error',
|
||||||
() {
|
() {
|
||||||
@ -496,3 +551,21 @@ class ImplementsCameraPlatform implements CameraPlatform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ExtendsCameraPlatform extends CameraPlatform {}
|
class ExtendsCameraPlatform extends CameraPlatform {}
|
||||||
|
|
||||||
|
class OverriddenCameraPlatform extends CameraPlatform {
|
||||||
|
OverriddenCameraPlatform(this._onCreateCameraCalled);
|
||||||
|
|
||||||
|
final void Function(
|
||||||
|
CameraDescription cameraDescription,
|
||||||
|
ResolutionPreset? resolutionPreset,
|
||||||
|
bool enableAudio,
|
||||||
|
) _onCreateCameraCalled;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<int> createCamera(
|
||||||
|
CameraDescription cameraDescription, ResolutionPreset? resolutionPreset,
|
||||||
|
{bool enableAudio = false}) {
|
||||||
|
_onCreateCameraCalled(cameraDescription, resolutionPreset, enableAudio);
|
||||||
|
return Future<int>.value(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -33,12 +33,17 @@ void main() {
|
|||||||
final MethodChannelCamera camera = MethodChannelCamera();
|
final MethodChannelCamera camera = MethodChannelCamera();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
final int cameraId = await camera.createCamera(
|
final int cameraId = await camera.createCameraWithSettings(
|
||||||
const CameraDescription(
|
const CameraDescription(
|
||||||
name: 'Test',
|
name: 'Test',
|
||||||
lensDirection: CameraLensDirection.back,
|
lensDirection: CameraLensDirection.back,
|
||||||
sensorOrientation: 0),
|
sensorOrientation: 0),
|
||||||
ResolutionPreset.high,
|
const MediaSettings(
|
||||||
|
resolutionPreset: ResolutionPreset.low,
|
||||||
|
fps: 15,
|
||||||
|
videoBitrate: 200000,
|
||||||
|
audioBitrate: 32000,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
@ -47,7 +52,10 @@ void main() {
|
|||||||
'create',
|
'create',
|
||||||
arguments: <String, Object?>{
|
arguments: <String, Object?>{
|
||||||
'cameraName': 'Test',
|
'cameraName': 'Test',
|
||||||
'resolutionPreset': 'high',
|
'resolutionPreset': 'low',
|
||||||
|
'fps': 15,
|
||||||
|
'videoBitrate': 200000,
|
||||||
|
'audioBitrate': 32000,
|
||||||
'enableAudio': false
|
'enableAudio': false
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -71,13 +79,19 @@ void main() {
|
|||||||
|
|
||||||
// Act
|
// Act
|
||||||
expect(
|
expect(
|
||||||
() => camera.createCamera(
|
() => camera.createCameraWithSettings(
|
||||||
const CameraDescription(
|
const CameraDescription(
|
||||||
name: 'Test',
|
name: 'Test',
|
||||||
lensDirection: CameraLensDirection.back,
|
lensDirection: CameraLensDirection.back,
|
||||||
sensorOrientation: 0,
|
sensorOrientation: 0,
|
||||||
),
|
),
|
||||||
ResolutionPreset.high,
|
const MediaSettings(
|
||||||
|
resolutionPreset: ResolutionPreset.low,
|
||||||
|
fps: 15,
|
||||||
|
videoBitrate: 200000,
|
||||||
|
audioBitrate: 32000,
|
||||||
|
enableAudio: true,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
throwsA(
|
throwsA(
|
||||||
isA<CameraException>()
|
isA<CameraException>()
|
||||||
@ -105,13 +119,19 @@ void main() {
|
|||||||
|
|
||||||
// Act
|
// Act
|
||||||
expect(
|
expect(
|
||||||
() => camera.createCamera(
|
() => camera.createCameraWithSettings(
|
||||||
const CameraDescription(
|
const CameraDescription(
|
||||||
name: 'Test',
|
name: 'Test',
|
||||||
lensDirection: CameraLensDirection.back,
|
lensDirection: CameraLensDirection.back,
|
||||||
sensorOrientation: 0,
|
sensorOrientation: 0,
|
||||||
),
|
),
|
||||||
ResolutionPreset.high,
|
const MediaSettings(
|
||||||
|
resolutionPreset: ResolutionPreset.low,
|
||||||
|
fps: 15,
|
||||||
|
videoBitrate: 200000,
|
||||||
|
audioBitrate: 32000,
|
||||||
|
enableAudio: true,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
throwsA(
|
throwsA(
|
||||||
isA<CameraException>()
|
isA<CameraException>()
|
||||||
@ -167,13 +187,19 @@ void main() {
|
|||||||
'initialize': null
|
'initialize': null
|
||||||
});
|
});
|
||||||
final MethodChannelCamera camera = MethodChannelCamera();
|
final MethodChannelCamera camera = MethodChannelCamera();
|
||||||
final int cameraId = await camera.createCamera(
|
final int cameraId = await camera.createCameraWithSettings(
|
||||||
const CameraDescription(
|
const CameraDescription(
|
||||||
name: 'Test',
|
name: 'Test',
|
||||||
lensDirection: CameraLensDirection.back,
|
lensDirection: CameraLensDirection.back,
|
||||||
sensorOrientation: 0,
|
sensorOrientation: 0,
|
||||||
),
|
),
|
||||||
ResolutionPreset.high,
|
const MediaSettings(
|
||||||
|
resolutionPreset: ResolutionPreset.low,
|
||||||
|
fps: 15,
|
||||||
|
videoBitrate: 200000,
|
||||||
|
audioBitrate: 32000,
|
||||||
|
enableAudio: true,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
@ -214,13 +240,19 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
final MethodChannelCamera camera = MethodChannelCamera();
|
final MethodChannelCamera camera = MethodChannelCamera();
|
||||||
final int cameraId = await camera.createCamera(
|
final int cameraId = await camera.createCameraWithSettings(
|
||||||
const CameraDescription(
|
const CameraDescription(
|
||||||
name: 'Test',
|
name: 'Test',
|
||||||
lensDirection: CameraLensDirection.back,
|
lensDirection: CameraLensDirection.back,
|
||||||
sensorOrientation: 0,
|
sensorOrientation: 0,
|
||||||
),
|
),
|
||||||
ResolutionPreset.high,
|
const MediaSettings(
|
||||||
|
resolutionPreset: ResolutionPreset.low,
|
||||||
|
fps: 15,
|
||||||
|
videoBitrate: 200000,
|
||||||
|
audioBitrate: 32000,
|
||||||
|
enableAudio: true,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
final Future<void> initializeFuture = camera.initializeCamera(cameraId);
|
final Future<void> initializeFuture = camera.initializeCamera(cameraId);
|
||||||
camera.cameraEventStreamController.add(CameraInitializedEvent(
|
camera.cameraEventStreamController.add(CameraInitializedEvent(
|
||||||
@ -262,13 +294,19 @@ void main() {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
camera = MethodChannelCamera();
|
camera = MethodChannelCamera();
|
||||||
cameraId = await camera.createCamera(
|
cameraId = await camera.createCameraWithSettings(
|
||||||
const CameraDescription(
|
const CameraDescription(
|
||||||
name: 'Test',
|
name: 'Test',
|
||||||
lensDirection: CameraLensDirection.back,
|
lensDirection: CameraLensDirection.back,
|
||||||
sensorOrientation: 0,
|
sensorOrientation: 0,
|
||||||
),
|
),
|
||||||
ResolutionPreset.high,
|
const MediaSettings(
|
||||||
|
resolutionPreset: ResolutionPreset.low,
|
||||||
|
fps: 15,
|
||||||
|
videoBitrate: 200000,
|
||||||
|
audioBitrate: 32000,
|
||||||
|
enableAudio: true,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
final Future<void> initializeFuture = camera.initializeCamera(cameraId);
|
final Future<void> initializeFuture = camera.initializeCamera(cameraId);
|
||||||
camera.cameraEventStreamController.add(CameraInitializedEvent(
|
camera.cameraEventStreamController.add(CameraInitializedEvent(
|
||||||
@ -432,13 +470,19 @@ void main() {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
camera = MethodChannelCamera();
|
camera = MethodChannelCamera();
|
||||||
cameraId = await camera.createCamera(
|
cameraId = await camera.createCameraWithSettings(
|
||||||
const CameraDescription(
|
const CameraDescription(
|
||||||
name: 'Test',
|
name: 'Test',
|
||||||
lensDirection: CameraLensDirection.back,
|
lensDirection: CameraLensDirection.back,
|
||||||
sensorOrientation: 0,
|
sensorOrientation: 0,
|
||||||
),
|
),
|
||||||
ResolutionPreset.high,
|
const MediaSettings(
|
||||||
|
resolutionPreset: ResolutionPreset.low,
|
||||||
|
fps: 15,
|
||||||
|
videoBitrate: 200000,
|
||||||
|
audioBitrate: 32000,
|
||||||
|
enableAudio: true,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
final Future<void> initializeFuture = camera.initializeCamera(cameraId);
|
final Future<void> initializeFuture = camera.initializeCamera(cameraId);
|
||||||
camera.cameraEventStreamController.add(
|
camera.cameraEventStreamController.add(
|
||||||
|
@ -0,0 +1,223 @@
|
|||||||
|
// 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: always_specify_types
|
||||||
|
|
||||||
|
import 'package:camera_platform_interface/camera_platform_interface.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
test(
|
||||||
|
'MediaSettings non-parametrized constructor should have correct initial values',
|
||||||
|
() {
|
||||||
|
const MediaSettings settingsWithNoParameters = MediaSettings();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
settingsWithNoParameters.resolutionPreset,
|
||||||
|
isNull,
|
||||||
|
reason:
|
||||||
|
'MediaSettings constructor should have null default resolutionPreset',
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
settingsWithNoParameters.fps,
|
||||||
|
isNull,
|
||||||
|
reason: 'MediaSettings constructor should have null default fps',
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
settingsWithNoParameters.videoBitrate,
|
||||||
|
isNull,
|
||||||
|
reason: 'MediaSettings constructor should have null default videoBitrate',
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
settingsWithNoParameters.audioBitrate,
|
||||||
|
isNull,
|
||||||
|
reason: 'MediaSettings constructor should have null default audioBitrate',
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
settingsWithNoParameters.enableAudio,
|
||||||
|
isFalse,
|
||||||
|
reason: 'MediaSettings constructor should have false default enableAudio',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('MediaSettings fps should hold parameters', () {
|
||||||
|
const MediaSettings settings = MediaSettings(
|
||||||
|
resolutionPreset: ResolutionPreset.low,
|
||||||
|
fps: 20,
|
||||||
|
videoBitrate: 128000,
|
||||||
|
audioBitrate: 32000,
|
||||||
|
enableAudio: true,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
settings.resolutionPreset,
|
||||||
|
ResolutionPreset.low,
|
||||||
|
reason:
|
||||||
|
'MediaSettings constructor should hold resolutionPreset parameter',
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
settings.fps,
|
||||||
|
20,
|
||||||
|
reason: 'MediaSettings constructor should hold fps parameter',
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
settings.videoBitrate,
|
||||||
|
128000,
|
||||||
|
reason: 'MediaSettings constructor should hold videoBitrate parameter',
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
settings.audioBitrate,
|
||||||
|
32000,
|
||||||
|
reason: 'MediaSettings constructor should hold audioBitrate parameter',
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
settings.enableAudio,
|
||||||
|
true,
|
||||||
|
reason: 'MediaSettings constructor should hold enableAudio parameter',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('MediaSettings hash should be Object.hash of passed parameters', () {
|
||||||
|
const MediaSettings settings = MediaSettings(
|
||||||
|
resolutionPreset: ResolutionPreset.low,
|
||||||
|
fps: 20,
|
||||||
|
videoBitrate: 128000,
|
||||||
|
audioBitrate: 32000,
|
||||||
|
enableAudio: true,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
settings.hashCode,
|
||||||
|
Object.hash(ResolutionPreset.low, 20, 128000, 32000, true),
|
||||||
|
reason:
|
||||||
|
'MediaSettings hash() should be equal to Object.hash of parameters',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
group('MediaSettings == operator', () {
|
||||||
|
const ResolutionPreset preset1 = ResolutionPreset.low;
|
||||||
|
const int fps1 = 20;
|
||||||
|
const int videoBitrate1 = 128000;
|
||||||
|
const int audioBitrate1 = 32000;
|
||||||
|
const bool enableAudio1 = true;
|
||||||
|
|
||||||
|
const ResolutionPreset preset2 = ResolutionPreset.high;
|
||||||
|
const int fps2 = fps1 + 10;
|
||||||
|
const int videoBitrate2 = videoBitrate1 * 2;
|
||||||
|
const int audioBitrate2 = audioBitrate1 * 2;
|
||||||
|
const bool enableAudio2 = !enableAudio1;
|
||||||
|
|
||||||
|
const MediaSettings settings1 = MediaSettings(
|
||||||
|
resolutionPreset: ResolutionPreset.low,
|
||||||
|
fps: 20,
|
||||||
|
videoBitrate: 128000,
|
||||||
|
audioBitrate: 32000,
|
||||||
|
enableAudio: true,
|
||||||
|
);
|
||||||
|
|
||||||
|
test('should compare resolutionPreset', () {
|
||||||
|
const MediaSettings settings2 = MediaSettings(
|
||||||
|
resolutionPreset: preset2,
|
||||||
|
fps: fps1,
|
||||||
|
videoBitrate: videoBitrate1,
|
||||||
|
audioBitrate: audioBitrate1,
|
||||||
|
enableAudio: enableAudio1,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(settings1 == settings2, isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should compare fps', () {
|
||||||
|
const MediaSettings settings2 = MediaSettings(
|
||||||
|
resolutionPreset: preset1,
|
||||||
|
fps: fps2,
|
||||||
|
videoBitrate: videoBitrate1,
|
||||||
|
audioBitrate: audioBitrate1,
|
||||||
|
enableAudio: enableAudio1,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(settings1 == settings2, isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should compare videoBitrate', () {
|
||||||
|
const MediaSettings settings2 = MediaSettings(
|
||||||
|
resolutionPreset: preset1,
|
||||||
|
fps: fps1,
|
||||||
|
videoBitrate: videoBitrate2,
|
||||||
|
audioBitrate: audioBitrate1,
|
||||||
|
enableAudio: enableAudio1,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(settings1 == settings2, isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should compare audioBitrate', () {
|
||||||
|
const MediaSettings settings2 = MediaSettings(
|
||||||
|
resolutionPreset: preset1,
|
||||||
|
fps: fps1,
|
||||||
|
videoBitrate: videoBitrate1,
|
||||||
|
audioBitrate: audioBitrate2,
|
||||||
|
enableAudio: enableAudio1,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(settings1 == settings2, isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should compare enableAudio', () {
|
||||||
|
const MediaSettings settings2 = MediaSettings(
|
||||||
|
resolutionPreset: preset1,
|
||||||
|
fps: fps1,
|
||||||
|
videoBitrate: videoBitrate1,
|
||||||
|
audioBitrate: audioBitrate1,
|
||||||
|
// ignore: avoid_redundant_argument_values
|
||||||
|
enableAudio: enableAudio2,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(settings1 == settings2, isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return true when all parameters are equal', () {
|
||||||
|
const MediaSettings sameSettings = MediaSettings(
|
||||||
|
resolutionPreset: preset1,
|
||||||
|
fps: fps1,
|
||||||
|
videoBitrate: videoBitrate1,
|
||||||
|
audioBitrate: audioBitrate1,
|
||||||
|
enableAudio: enableAudio1,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
settings1 == sameSettings,
|
||||||
|
isTrue,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Identical objects should be equal', () {
|
||||||
|
const MediaSettings settingsIdentical = settings1;
|
||||||
|
|
||||||
|
expect(
|
||||||
|
settings1 == settingsIdentical,
|
||||||
|
isTrue,
|
||||||
|
reason:
|
||||||
|
'MediaSettings == operator should return true for identical objects',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Objects of different types should be non-equal', () {
|
||||||
|
expect(
|
||||||
|
settings1 == Object(),
|
||||||
|
isFalse,
|
||||||
|
reason:
|
||||||
|
'MediaSettings == operator should return false for objects of different types',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
Reference in New Issue
Block a user