Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
///
/// If a preset is not available on the camera being used a preset of lower quality will be selected automatically.
enum ResolutionPreset {
/// 352x288 on iOS, 240p (320x240) on Android
/// 352x288 on iOS, 240p (320x240) on Android and Web
low,

/// 480p (640x480 on iOS, 720x480 on Android)
/// 480p (640x480 on iOS, 720x480 on Android and Web)
medium,

/// 720p (1280x720)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// found in the LICENSE file.

import 'dart:html';
import 'dart:ui';

import 'package:camera_platform_interface/camera_platform_interface.dart';
import 'package:camera_web/src/camera_settings.dart';
Expand Down Expand Up @@ -204,6 +205,100 @@ void main() {
);
});
});

group('mapFacingModeToCameraType', () {
testWidgets(
'returns user '
'when the facing mode is user', (tester) async {
expect(
settings.mapFacingModeToCameraType('user'),
equals(CameraType.user),
);
});

testWidgets(
'returns environment '
'when the facing mode is environment', (tester) async {
expect(
settings.mapFacingModeToCameraType('environment'),
equals(CameraType.environment),
);
});

testWidgets(
'returns user '
'when the facing mode is left', (tester) async {
expect(
settings.mapFacingModeToCameraType('left'),
equals(CameraType.user),
);
});

testWidgets(
'returns user '
'when the facing mode is right', (tester) async {
expect(
settings.mapFacingModeToCameraType('right'),
equals(CameraType.user),
);
});
});

group('mapResolutionPresetToSize', () {
testWidgets(
'returns 3840x2160 '
'when the resolution preset is max', (tester) async {
expect(
settings.mapResolutionPresetToSize(ResolutionPreset.max),
equals(Size(3840, 2160)),
);
});

testWidgets(
'returns 3840x2160 '
'when the resolution preset is ultraHigh', (tester) async {
expect(
settings.mapResolutionPresetToSize(ResolutionPreset.ultraHigh),
equals(Size(3840, 2160)),
);
});

testWidgets(
'returns 1920x1080 '
'when the resolution preset is veryHigh', (tester) async {
expect(
settings.mapResolutionPresetToSize(ResolutionPreset.veryHigh),
equals(Size(1920, 1080)),
);
});

testWidgets(
'returns 1280x720 '
'when the resolution preset is high', (tester) async {
expect(
settings.mapResolutionPresetToSize(ResolutionPreset.high),
equals(Size(1280, 720)),
);
});

testWidgets(
'returns 720x480 '
'when the resolution preset is medium', (tester) async {
expect(
settings.mapResolutionPresetToSize(ResolutionPreset.medium),
equals(Size(720, 480)),
);
});

testWidgets(
'returns 320x240 '
'when the resolution preset is low', (tester) async {
expect(
settings.mapResolutionPresetToSize(ResolutionPreset.low),
equals(Size(320, 240)),
);
});
});
});
}

Expand Down
144 changes: 134 additions & 10 deletions packages/camera/camera_web/example/integration_test/camera_web_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
// found in the LICENSE file.

import 'dart:html';
import 'dart:ui';

import 'package:camera_platform_interface/camera_platform_interface.dart';
import 'package:camera_web/camera_web.dart';
import 'package:camera_web/src/camera.dart';
import 'package:camera_web/src/camera_settings.dart';
import 'package:camera_web/src/types/types.dart';
import 'package:flutter/services.dart';
Expand Down Expand Up @@ -296,18 +298,140 @@ void main() {
});
});

testWidgets('createCamera throws UnimplementedError', (tester) async {
expect(
() => CameraPlatform.instance.createCamera(
CameraDescription(
group('createCamera', () {
testWidgets(
'throws CameraException '
'with missingMetadata error '
'if there is no metadata '
'for the given camera description', (tester) async {
expect(
() => CameraPlatform.instance.createCamera(
CameraDescription(
name: 'name',
lensDirection: CameraLensDirection.back,
sensorOrientation: 0,
),
ResolutionPreset.ultraHigh,
),
throwsA(
isA<CameraException>().having(
(e) => e.code,
'code',
CameraErrorCodes.missingMetadata,
),
),
);
});

group('creates a camera', () {
const ultraHighResolutionSize = Size(3840, 2160);
const maxResolutionSize = Size(3840, 2160);

late CameraDescription cameraDescription;
late CameraMetadata cameraMetadata;

setUp(() {
cameraDescription = CameraDescription(
name: 'name',
lensDirection: CameraLensDirection.external,
lensDirection: CameraLensDirection.front,
sensorOrientation: 0,
),
ResolutionPreset.medium,
),
throwsUnimplementedError,
);
);

cameraMetadata = CameraMetadata(
deviceId: 'deviceId',
facingMode: 'user',
);

// Add metadata for the camera description.
(CameraPlatform.instance as CameraPlugin)
.camerasMetadata[cameraDescription] = cameraMetadata;

when(
() => cameraSettings.mapFacingModeToCameraType('user'),
).thenReturn(CameraType.user);
});

testWidgets('with appropriate options', (tester) async {
when(
() => cameraSettings
.mapResolutionPresetToSize(ResolutionPreset.ultraHigh),
).thenReturn(ultraHighResolutionSize);

final cameraId = await CameraPlatform.instance.createCamera(
cameraDescription,
ResolutionPreset.ultraHigh,
enableAudio: true,
);

expect(
(CameraPlatform.instance as CameraPlugin).cameras[cameraId],
isA<Camera>()
.having(
(camera) => camera.textureId,
'textureId',
cameraId,
)
.having(
(camera) => camera.window,
'window',
window,
)
.having(
(camera) => camera.options,
'options',
CameraOptions(
audio: AudioConstraints(enabled: true),
video: VideoConstraints(
facingMode: FacingModeConstraint(CameraType.user),
width: VideoSizeConstraint(
ideal: ultraHighResolutionSize.width.toInt(),
),
height: VideoSizeConstraint(
ideal: ultraHighResolutionSize.height.toInt(),
),
deviceId: cameraMetadata.deviceId,
),
),
),
);
});

testWidgets(
'with a max resolution preset '
'and enabled audio set to false '
'when no options are specified', (tester) async {
when(
() =>
cameraSettings.mapResolutionPresetToSize(ResolutionPreset.max),
).thenReturn(maxResolutionSize);

final cameraId = await CameraPlatform.instance.createCamera(
cameraDescription,
null,
);

expect(
(CameraPlatform.instance as CameraPlugin).cameras[cameraId],
isA<Camera>().having(
(camera) => camera.options,
'options',
CameraOptions(
audio: AudioConstraints(enabled: false),
video: VideoConstraints(
facingMode: FacingModeConstraint(CameraType.user),
width: VideoSizeConstraint(
ideal: maxResolutionSize.width.toInt(),
),
height: VideoSizeConstraint(
ideal: maxResolutionSize.height.toInt(),
),
deviceId: cameraMetadata.deviceId,
),
),
),
);
});
});
});

testWidgets('initializeCamera throws UnimplementedError', (tester) async {
Expand Down
35 changes: 35 additions & 0 deletions packages/camera/camera_web/lib/src/camera_settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// found in the LICENSE file.

import 'dart:html' as html;
import 'dart:ui';

import 'package:camera_platform_interface/camera_platform_interface.dart';
import 'package:camera_web/src/types/types.dart';
Expand Down Expand Up @@ -105,4 +106,38 @@ class CameraSettings {
return CameraLensDirection.external;
}
}

/// Maps the given [facingMode] to [CameraType].
///
/// See [CameraMetadata.facingMode] for more details.
CameraType mapFacingModeToCameraType(String facingMode) {
switch (facingMode) {
case 'user':
return CameraType.user;
case 'environment':
return CameraType.environment;
case 'left':
case 'right':
default:
return CameraType.user;
}
}

/// Maps the given [resolutionPreset] to [Size].
Size mapResolutionPresetToSize(ResolutionPreset resolutionPreset) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this take in to account the screen orientation? I don't remember if we had to flip the w/h on the photobooth when the app was rotated? Do you remember @felangel?

Copy link
Contributor Author

@bselwe bselwe Jul 23, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I can see that photobooth records the screen orientation when the photo is being captured. Then, the photo is displayed inside the AspectRatio widget with an aspect ratio based on that orientation but not sure if that has anything to do with flipping the w/h. 🤔

switch (resolutionPreset) {
case ResolutionPreset.max:
case ResolutionPreset.ultraHigh:
return Size(3840, 2160);
case ResolutionPreset.veryHigh:
return Size(1920, 1080);
case ResolutionPreset.high:
return Size(1280, 720);
case ResolutionPreset.medium:
return Size(720, 480);
case ResolutionPreset.low:
default:
return Size(320, 240);
}
}
}
Loading