camera: add ELinuxCamera dartPluginClass (#81)

Fixed https://github.com/sony/flutter-elinux/issues/211

Signed-off-by: Hidenori Matsubayashi <[email protected]>
This commit is contained in:
Hidenori Matsubayashi
2023-08-28 12:37:20 +00:00
committed by GitHub
parent 96106f35e7
commit 57f3aa88bf
9 changed files with 800 additions and 5 deletions
+3
View File
@@ -1,3 +1,6 @@
## 0.3.2
* Add ELinuxCamera (camera dartPluginClass for eLinux) for flutter 3.13.
## 0.3.1 ## 0.3.1
* Update for flutter official camera plugin v0.10.5+3 * Update for flutter official camera plugin v0.10.5+3
+36 -2
View File
@@ -86,6 +86,12 @@ class CameraPlugin : public flutter::Plugin {
void HandleTakePictureCall( void HandleTakePictureCall(
const flutter::EncodableValue* message, const flutter::EncodableValue* message,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result); std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result);
void HandleGetMinExposureOffsetCall(
const flutter::EncodableValue* message,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result);
void HandleGetMaxExposureOffsetCall(
const flutter::EncodableValue* message,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result);
void HandleStartImageStreamCall( void HandleStartImageStreamCall(
const flutter::EncodableValue* message, const flutter::EncodableValue* message,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result); std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result);
@@ -169,9 +175,9 @@ void CameraPlugin::HandleMethodCall(
} else if (!method_name.compare(kCameraChannelApiSetExposurePoint)) { } else if (!method_name.compare(kCameraChannelApiSetExposurePoint)) {
result->NotImplemented(); result->NotImplemented();
} else if (!method_name.compare(kCameraChannelApiGetMinExposureOffset)) { } else if (!method_name.compare(kCameraChannelApiGetMinExposureOffset)) {
result->NotImplemented(); HandleGetMinExposureOffsetCall(method_call.arguments(), std::move(result));
} else if (!method_name.compare(kCameraChannelApiGetMaxExposureOffset)) { } else if (!method_name.compare(kCameraChannelApiGetMaxExposureOffset)) {
result->NotImplemented(); HandleGetMaxExposureOffsetCall(method_call.arguments(), std::move(result));
} else if (!method_name.compare(kCameraChannelApiGetExposureOffsetStepSize)) { } else if (!method_name.compare(kCameraChannelApiGetExposureOffsetStepSize)) {
result->NotImplemented(); result->NotImplemented();
} else if (!method_name.compare(kCameraChannelApiSetExposureOffset)) { } else if (!method_name.compare(kCameraChannelApiSetExposureOffset)) {
@@ -308,6 +314,34 @@ void CameraPlugin::HandleTakePictureCall(
}); });
} }
void CameraPlugin::HandleGetMinExposureOffsetCall(
const flutter::EncodableValue* message,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
if (!camera_) {
result->Error("Not found an active camera",
"Check for creating a camera device");
return;
}
// TODO: Implement exposure control support
double value = 0.0;
result->Success(flutter::EncodableValue(value));
}
void CameraPlugin::HandleGetMaxExposureOffsetCall(
const flutter::EncodableValue* message,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
if (!camera_) {
result->Error("Not found an active camera",
"Check for creating a camera device");
return;
}
// TODO: Implement exposure control support
double value = 0.0;
result->Success(flutter::EncodableValue(value));
}
void CameraPlugin::HandleStartImageStreamCall( void CameraPlugin::HandleStartImageStreamCall(
const flutter::EncodableValue* message, const flutter::EncodableValue* message,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) { std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
@@ -8,7 +8,7 @@
#include <flutter/standard_method_codec.h> #include <flutter/standard_method_codec.h>
namespace { namespace {
constexpr char kChannelName[] = "flutter.io/cameraPlugin/camera"; constexpr char kChannelName[] = "plugins.flutter.io/camera/camera";
constexpr char kChannelMethodInitialized[] = "initialized"; constexpr char kChannelMethodInitialized[] = "initialized";
}; // namespace }; // namespace
@@ -8,7 +8,7 @@
#include <flutter/standard_method_codec.h> #include <flutter/standard_method_codec.h>
namespace { namespace {
constexpr char kChannelName[] = "flutter.io/cameraPlugin/device"; constexpr char kChannelName[] = "plugins.flutter.io/camera/fromPlatform";
constexpr char kChannelMethodOrientationChanged[] = "orientation_changed"; constexpr char kChannelMethodOrientationChanged[] = "orientation_changed";
constexpr char kOrientation[] = "orientation"; constexpr char kOrientation[] = "orientation";
+6
View File
@@ -0,0 +1,6 @@
// Copyright 2023 Sony Group Corporation. All rights reserved.
// 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.
export 'src/elinux_camera.dart';
+645
View File
@@ -0,0 +1,645 @@
// Copyright 2023 Sony Group Corporation. All rights reserved.
// 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.
import 'dart:async';
import 'dart:math';
import 'package:camera_platform_interface/camera_platform_interface.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:stream_transform/stream_transform.dart';
import 'type_conversion.dart';
import 'utils.dart';
const MethodChannel _channel =
MethodChannel('plugins.flutter.io/camera');
/// The ELinux implementation of [CameraPlatform] that uses method channels.
class ELinuxCamera extends CameraPlatform {
/// Registers this class as the default instance of [CameraPlatform].
static void registerWith() {
CameraPlatform.instance = ELinuxCamera();
}
final Map<int, MethodChannel> _channels = <int, MethodChannel>{};
/// The name of the channel that device events from the platform side are
/// sent on.
@visibleForTesting
static const String deviceEventChannelName =
'plugins.flutter.io/camera/fromPlatform';
/// The controller we need to broadcast the different events coming
/// from handleMethodCall, specific to camera events.
///
/// It is a `broadcast` because multiple controllers will connect to
/// different stream views of this Controller.
/// This is only exposed for test purposes. It shouldn't be used by clients of
/// the plugin as it may break or change at any time.
@visibleForTesting
final StreamController<CameraEvent> cameraEventStreamController =
StreamController<CameraEvent>.broadcast();
/// The controller we need to broadcast the different events coming
/// from handleMethodCall, specific to general device events.
///
/// It is a `broadcast` because multiple controllers will connect to
/// different stream views of this Controller.
late final StreamController<DeviceEvent> _deviceEventStreamController =
_createDeviceEventStreamController();
StreamController<DeviceEvent> _createDeviceEventStreamController() {
// Set up the method handler lazily.
const MethodChannel channel = MethodChannel(deviceEventChannelName);
channel.setMethodCallHandler(_handleDeviceMethodCall);
return StreamController<DeviceEvent>.broadcast();
}
// The stream to receive frames from the native code.
StreamSubscription<dynamic>? _platformImageStreamSubscription;
// The stream for vending frames to platform interface clients.
StreamController<CameraImageData>? _frameStreamController;
Stream<CameraEvent> _cameraEvents(int cameraId) =>
cameraEventStreamController.stream
.where((CameraEvent event) => event.cameraId == cameraId);
@override
Future<List<CameraDescription>> availableCameras() async {
try {
final List<Map<dynamic, dynamic>>? cameras = await _channel
.invokeListMethod<Map<dynamic, dynamic>>('availableCameras');
if (cameras == null) {
return <CameraDescription>[];
}
return cameras.map((Map<dynamic, dynamic> camera) {
return CameraDescription(
name: camera['name']! as String,
lensDirection:
parseCameraLensDirection(camera['lensFacing']! as String),
sensorOrientation: camera['sensorOrientation']! as int,
);
}).toList();
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}
@override
Future<int> createCamera(
CameraDescription cameraDescription,
ResolutionPreset? resolutionPreset, {
bool enableAudio = false,
}) async {
try {
final Map<String, dynamic>? reply = await _channel
.invokeMapMethod<String, dynamic>('create', <String, dynamic>{
'cameraName': cameraDescription.name,
'resolutionPreset': resolutionPreset != null
? _serializeResolutionPreset(resolutionPreset)
: null,
'enableAudio': enableAudio,
});
return reply!['cameraId']! as int;
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}
@override
Future<void> initializeCamera(
int cameraId, {
ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown,
}) {
_channels.putIfAbsent(cameraId, () {
final MethodChannel channel =
MethodChannel('plugins.flutter.io/camera/camera$cameraId');
channel.setMethodCallHandler(
(MethodCall call) => handleCameraMethodCall(call, cameraId));
return channel;
});
final Completer<void> completer = Completer<void>();
onCameraInitialized(cameraId).first.then((CameraInitializedEvent value) {
completer.complete();
});
_channel.invokeMapMethod<String, dynamic>(
'initialize',
<String, dynamic>{
'cameraId': cameraId,
'imageFormatGroup': imageFormatGroup.name(),
},
).catchError(
// TODO(srawlins): This should return a value of the future's type. This
// will fail upcoming analysis checks with
// https://github.com/flutter/flutter/issues/105750.
// ignore: body_might_complete_normally_catch_error
(Object error, StackTrace stackTrace) {
if (error is! PlatformException) {
// ignore: only_throw_errors
throw error;
}
completer.completeError(
CameraException(error.code, error.message),
stackTrace,
);
},
);
return completer.future;
}
@override
Future<void> dispose(int cameraId) async {
if (_channels.containsKey(cameraId)) {
final MethodChannel? cameraChannel = _channels[cameraId];
cameraChannel?.setMethodCallHandler(null);
_channels.remove(cameraId);
}
await _channel.invokeMethod<void>(
'dispose',
<String, dynamic>{'cameraId': cameraId},
);
}
@override
Stream<CameraInitializedEvent> onCameraInitialized(int cameraId) {
return _cameraEvents(cameraId).whereType<CameraInitializedEvent>();
}
@override
Stream<CameraResolutionChangedEvent> onCameraResolutionChanged(int cameraId) {
return _cameraEvents(cameraId).whereType<CameraResolutionChangedEvent>();
}
@override
Stream<CameraClosingEvent> onCameraClosing(int cameraId) {
return _cameraEvents(cameraId).whereType<CameraClosingEvent>();
}
@override
Stream<CameraErrorEvent> onCameraError(int cameraId) {
return _cameraEvents(cameraId).whereType<CameraErrorEvent>();
}
@override
Stream<VideoRecordedEvent> onVideoRecordedEvent(int cameraId) {
return _cameraEvents(cameraId).whereType<VideoRecordedEvent>();
}
@override
Stream<DeviceOrientationChangedEvent> onDeviceOrientationChanged() {
return _deviceEventStreamController.stream
.whereType<DeviceOrientationChangedEvent>();
}
@override
Future<void> lockCaptureOrientation(
int cameraId,
DeviceOrientation orientation,
) async {
await _channel.invokeMethod<String>(
'lockCaptureOrientation',
<String, dynamic>{
'cameraId': cameraId,
'orientation': serializeDeviceOrientation(orientation)
},
);
}
@override
Future<void> unlockCaptureOrientation(int cameraId) async {
await _channel.invokeMethod<String>(
'unlockCaptureOrientation',
<String, dynamic>{'cameraId': cameraId},
);
}
@override
Future<XFile> takePicture(int cameraId) async {
final String? path = await _channel.invokeMethod<String>(
'takePicture',
<String, dynamic>{'cameraId': cameraId},
);
if (path == null) {
throw CameraException(
'INVALID_PATH',
'The platform "$defaultTargetPlatform" did not return a path while reporting success. The platform should always return a valid path or report an error.',
);
}
return XFile(path);
}
@override
Future<void> prepareForVideoRecording() =>
_channel.invokeMethod<void>('prepareForVideoRecording');
@override
Future<void> startVideoRecording(int cameraId,
{Duration? maxVideoDuration}) async {
return startVideoCapturing(
VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration));
}
@override
Future<void> startVideoCapturing(VideoCaptureOptions options) async {
await _channel.invokeMethod<void>(
'startVideoRecording',
<String, dynamic>{
'cameraId': options.cameraId,
'maxVideoDuration': options.maxDuration?.inMilliseconds,
'enableStream': options.streamCallback != null,
},
);
if (options.streamCallback != null) {
_installStreamController().stream.listen(options.streamCallback);
_startStreamListener();
}
}
@override
Future<XFile> stopVideoRecording(int cameraId) async {
final String? path = await _channel.invokeMethod<String>(
'stopVideoRecording',
<String, dynamic>{'cameraId': cameraId},
);
if (path == null) {
throw CameraException(
'INVALID_PATH',
'The platform "$defaultTargetPlatform" did not return a path while reporting success. The platform should always return a valid path or report an error.',
);
}
return XFile(path);
}
@override
Future<void> pauseVideoRecording(int cameraId) => _channel.invokeMethod<void>(
'pauseVideoRecording',
<String, dynamic>{'cameraId': cameraId},
);
@override
Future<void> resumeVideoRecording(int cameraId) =>
_channel.invokeMethod<void>(
'resumeVideoRecording',
<String, dynamic>{'cameraId': cameraId},
);
@override
Stream<CameraImageData> onStreamedFrameAvailable(int cameraId,
{CameraImageStreamOptions? options}) {
_installStreamController(onListen: _onFrameStreamListen);
return _frameStreamController!.stream;
}
StreamController<CameraImageData> _installStreamController(
{Function()? onListen}) {
_frameStreamController = StreamController<CameraImageData>(
onListen: onListen ?? () {},
onPause: _onFrameStreamPauseResume,
onResume: _onFrameStreamPauseResume,
onCancel: _onFrameStreamCancel,
);
return _frameStreamController!;
}
void _onFrameStreamListen() {
_startPlatformStream();
}
Future<void> _startPlatformStream() async {
await _channel.invokeMethod<void>('startImageStream');
_startStreamListener();
}
void _startStreamListener() {
const EventChannel cameraEventChannel =
EventChannel('plugins.flutter.io/camera/imageStream');
_platformImageStreamSubscription =
cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) {
_frameStreamController!
.add(cameraImageFromPlatformData(imageData as Map<dynamic, dynamic>));
});
}
FutureOr<void> _onFrameStreamCancel() async {
await _channel.invokeMethod<void>('stopImageStream');
await _platformImageStreamSubscription?.cancel();
_platformImageStreamSubscription = null;
_frameStreamController = null;
}
void _onFrameStreamPauseResume() {
throw CameraException('InvalidCall',
'Pause and resume are not supported for onStreamedFrameAvailable');
}
@override
Future<void> setFlashMode(int cameraId, FlashMode mode) =>
_channel.invokeMethod<void>(
'setFlashMode',
<String, dynamic>{
'cameraId': cameraId,
'mode': _serializeFlashMode(mode),
},
);
@override
Future<void> setExposureMode(int cameraId, ExposureMode mode) =>
_channel.invokeMethod<void>(
'setExposureMode',
<String, dynamic>{
'cameraId': cameraId,
'mode': serializeExposureMode(mode),
},
);
@override
Future<void> setExposurePoint(int cameraId, Point<double>? point) {
assert(point == null || point.x >= 0 && point.x <= 1);
assert(point == null || point.y >= 0 && point.y <= 1);
return _channel.invokeMethod<void>(
'setExposurePoint',
<String, dynamic>{
'cameraId': cameraId,
'reset': point == null,
'x': point?.x,
'y': point?.y,
},
);
}
@override
Future<double> getMinExposureOffset(int cameraId) async {
final double? minExposureOffset = await _channel.invokeMethod<double>(
'getMinExposureOffset',
<String, dynamic>{'cameraId': cameraId},
);
return minExposureOffset!;
}
@override
Future<double> getMaxExposureOffset(int cameraId) async {
final double? maxExposureOffset = await _channel.invokeMethod<double>(
'getMaxExposureOffset',
<String, dynamic>{'cameraId': cameraId},
);
return maxExposureOffset!;
}
@override
Future<double> getExposureOffsetStepSize(int cameraId) async {
final double? stepSize = await _channel.invokeMethod<double>(
'getExposureOffsetStepSize',
<String, dynamic>{'cameraId': cameraId},
);
return stepSize!;
}
@override
Future<double> setExposureOffset(int cameraId, double offset) async {
final double? appliedOffset = await _channel.invokeMethod<double>(
'setExposureOffset',
<String, dynamic>{
'cameraId': cameraId,
'offset': offset,
},
);
return appliedOffset!;
}
@override
Future<void> setFocusMode(int cameraId, FocusMode mode) =>
_channel.invokeMethod<void>(
'setFocusMode',
<String, dynamic>{
'cameraId': cameraId,
'mode': serializeFocusMode(mode),
},
);
@override
Future<void> setFocusPoint(int cameraId, Point<double>? point) {
assert(point == null || point.x >= 0 && point.x <= 1);
assert(point == null || point.y >= 0 && point.y <= 1);
return _channel.invokeMethod<void>(
'setFocusPoint',
<String, dynamic>{
'cameraId': cameraId,
'reset': point == null,
'x': point?.x,
'y': point?.y,
},
);
}
@override
Future<double> getMaxZoomLevel(int cameraId) async {
final double? maxZoomLevel = await _channel.invokeMethod<double>(
'getMaxZoomLevel',
<String, dynamic>{'cameraId': cameraId},
);
return maxZoomLevel!;
}
@override
Future<double> getMinZoomLevel(int cameraId) async {
final double? minZoomLevel = await _channel.invokeMethod<double>(
'getMinZoomLevel',
<String, dynamic>{'cameraId': cameraId},
);
return minZoomLevel!;
}
@override
Future<void> setZoomLevel(int cameraId, double zoom) async {
try {
await _channel.invokeMethod<double>(
'setZoomLevel',
<String, dynamic>{
'cameraId': cameraId,
'zoom': zoom,
},
);
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}
@override
Future<void> pausePreview(int cameraId) async {
await _channel.invokeMethod<double>(
'pausePreview',
<String, dynamic>{'cameraId': cameraId},
);
}
@override
Future<void> resumePreview(int cameraId) async {
await _channel.invokeMethod<double>(
'resumePreview',
<String, dynamic>{'cameraId': cameraId},
);
}
@override
Future<void> setDescriptionWhileRecording(
CameraDescription description) async {
await _channel.invokeMethod<double>(
'setDescriptionWhileRecording',
<String, dynamic>{
'cameraName': description.name,
},
);
}
@override
Widget buildPreview(int cameraId) {
return Texture(textureId: cameraId);
}
/// Returns the flash mode as a String.
String _serializeFlashMode(FlashMode flashMode) {
switch (flashMode) {
case FlashMode.off:
return 'off';
case FlashMode.auto:
return 'auto';
case FlashMode.always:
return 'always';
case FlashMode.torch:
return 'torch';
}
// The enum comes from a different package, which could get a new value at
// any time, so provide a fallback that ensures this won't break when used
// with a version that contains new values. This is deliberately outside
// the switch rather than a `default` so that the linter will flag the
// switch as needing an update.
// ignore: dead_code
return 'off';
}
/// Returns the resolution preset as a String.
String _serializeResolutionPreset(ResolutionPreset resolutionPreset) {
switch (resolutionPreset) {
case ResolutionPreset.max:
return 'max';
case ResolutionPreset.ultraHigh:
return 'ultraHigh';
case ResolutionPreset.veryHigh:
return 'veryHigh';
case ResolutionPreset.high:
return 'high';
case ResolutionPreset.medium:
return 'medium';
case ResolutionPreset.low:
return 'low';
}
// The enum comes from a different package, which could get a new value at
// any time, so provide a fallback that ensures this won't break when used
// with a version that contains new values. This is deliberately outside
// the switch rather than a `default` so that the linter will flag the
// switch as needing an update.
// ignore: dead_code
return 'max';
}
/// Converts messages received from the native platform into device events.
Future<dynamic> _handleDeviceMethodCall(MethodCall call) async {
switch (call.method) {
case 'orientation_changed':
final Map<String, Object?> arguments = _getArgumentDictionary(call);
_deviceEventStreamController.add(DeviceOrientationChangedEvent(
deserializeDeviceOrientation(arguments['orientation']! as String)));
break;
default:
throw MissingPluginException();
}
}
/// Converts messages received from the native platform into camera events.
///
/// This is only exposed for test purposes. It shouldn't be used by clients of
/// the plugin as it may break or change at any time.
@visibleForTesting
Future<dynamic> handleCameraMethodCall(MethodCall call, int cameraId) async {
switch (call.method) {
case 'initialized':
final Map<String, Object?> arguments = _getArgumentDictionary(call);
cameraEventStreamController.add(CameraInitializedEvent(
cameraId,
arguments['previewWidth']! as double,
arguments['previewHeight']! as double,
deserializeExposureMode(arguments['exposureMode']! as String),
arguments['exposurePointSupported']! as bool,
deserializeFocusMode(arguments['focusMode']! as String),
arguments['focusPointSupported']! as bool,
));
break;
case 'resolution_changed':
final Map<String, Object?> arguments = _getArgumentDictionary(call);
cameraEventStreamController.add(CameraResolutionChangedEvent(
cameraId,
arguments['captureWidth']! as double,
arguments['captureHeight']! as double,
));
break;
case 'camera_closing':
cameraEventStreamController.add(CameraClosingEvent(
cameraId,
));
break;
case 'video_recorded':
final Map<String, Object?> arguments = _getArgumentDictionary(call);
cameraEventStreamController.add(VideoRecordedEvent(
cameraId,
XFile(arguments['path']! as String),
arguments['maxVideoDuration'] != null
? Duration(milliseconds: arguments['maxVideoDuration']! as int)
: null,
));
break;
case 'error':
final Map<String, Object?> arguments = _getArgumentDictionary(call);
cameraEventStreamController.add(CameraErrorEvent(
cameraId,
arguments['description']! as String,
));
break;
default:
throw MissingPluginException();
}
}
/// Returns the arguments of [call] as typed string-keyed Map.
///
/// This does not do any type validation, so is only safe to call if the
/// arguments are known to be a map.
Map<String, Object?> _getArgumentDictionary(MethodCall call) {
return (call.arguments as Map<Object?, Object?>).cast<String, Object?>();
}
}
@@ -0,0 +1,49 @@
// 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.
import 'dart:typed_data';
import 'package:camera_platform_interface/camera_platform_interface.dart';
/// Converts method channel call [data] for `receivedImageStreamData` to a
/// [CameraImageData].
CameraImageData cameraImageFromPlatformData(Map<dynamic, dynamic> data) {
return CameraImageData(
format: _cameraImageFormatFromPlatformData(data['format']),
height: data['height'] as int,
width: data['width'] as int,
lensAperture: data['lensAperture'] as double?,
sensorExposureTime: data['sensorExposureTime'] as int?,
sensorSensitivity: data['sensorSensitivity'] as double?,
planes: List<CameraImagePlane>.unmodifiable(
(data['planes'] as List<dynamic>).map<CameraImagePlane>(
(dynamic planeData) => _cameraImagePlaneFromPlatformData(
planeData as Map<dynamic, dynamic>))));
}
CameraImageFormat _cameraImageFormatFromPlatformData(dynamic data) {
return CameraImageFormat(_imageFormatGroupFromPlatformData(data), raw: data);
}
ImageFormatGroup _imageFormatGroupFromPlatformData(dynamic data) {
switch (data) {
case 35: // android.graphics.ImageFormat.YUV_420_888
return ImageFormatGroup.yuv420;
case 256: // android.graphics.ImageFormat.JPEG
return ImageFormatGroup.jpeg;
case 17: // android.graphics.ImageFormat.NV21
return ImageFormatGroup.nv21;
}
return ImageFormatGroup.unknown;
}
CameraImagePlane _cameraImagePlaneFromPlatformData(Map<dynamic, dynamic> data) {
return CameraImagePlane(
bytes: data['bytes'] as Uint8List,
bytesPerPixel: data['bytesPerPixel'] as int?,
bytesPerRow: data['bytesPerRow'] as int,
height: data['height'] as int?,
width: data['width'] as int?);
}
+56
View File
@@ -0,0 +1,56 @@
// 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.
import 'package:camera_platform_interface/camera_platform_interface.dart';
import 'package:flutter/services.dart';
/// Parses a string into a corresponding CameraLensDirection.
CameraLensDirection parseCameraLensDirection(String string) {
switch (string) {
case 'front':
return CameraLensDirection.front;
case 'back':
return CameraLensDirection.back;
case 'external':
return CameraLensDirection.external;
}
throw ArgumentError('Unknown CameraLensDirection value');
}
/// Returns the device orientation as a String.
String serializeDeviceOrientation(DeviceOrientation orientation) {
switch (orientation) {
case DeviceOrientation.portraitUp:
return 'portraitUp';
case DeviceOrientation.portraitDown:
return 'portraitDown';
case DeviceOrientation.landscapeRight:
return 'landscapeRight';
case DeviceOrientation.landscapeLeft:
return 'landscapeLeft';
}
// The enum comes from a different package, which could get a new value at
// any time, so provide a fallback that ensures this won't break when used
// with a version that contains new values. This is deliberately outside
// the switch rather than a `default` so that the linter will flag the
// switch as needing an update.
// ignore: dead_code
return 'portraitUp';
}
/// Returns the device orientation for a given String.
DeviceOrientation deserializeDeviceOrientation(String str) {
switch (str) {
case 'portraitUp':
return DeviceOrientation.portraitUp;
case 'portraitDown':
return DeviceOrientation.portraitDown;
case 'landscapeRight':
return DeviceOrientation.landscapeRight;
case 'landscapeLeft':
return DeviceOrientation.landscapeLeft;
default:
throw ArgumentError('"$str" is not a valid DeviceOrientation value');
}
}
+3 -1
View File
@@ -2,7 +2,7 @@ name: camera_elinux
description: A Flutter plugin for getting information about and controlling the description: A Flutter plugin for getting information about and controlling the
camera on eLinux. Supports previewing the camera feed, capturing images, capturing video, camera on eLinux. Supports previewing the camera feed, capturing images, capturing video,
and streaming image buffers to dart. and streaming image buffers to dart.
version: 0.3.1 version: 0.3.2
homepage: https://github.com/sony/flutter-elinux-plugins homepage: https://github.com/sony/flutter-elinux-plugins
repository: https://github.com/sony/flutter-elinux-plugins/tree/main/packages/camera repository: https://github.com/sony/flutter-elinux-plugins/tree/main/packages/camera
@@ -11,6 +11,7 @@ environment:
flutter: ">=3.3.0" flutter: ">=3.3.0"
dependencies: dependencies:
camera_platform_interface: ^2.5.0
flutter: flutter:
sdk: flutter sdk: flutter
@@ -19,3 +20,4 @@ flutter:
platforms: platforms:
elinux: elinux:
pluginClass: CameraElinuxPlugin pluginClass: CameraElinuxPlugin
dartPluginClass: ELinuxCamera