From 7a2a0fa0fa0dbbfd7ce3b2e032bbad28610ed0c6 Mon Sep 17 00:00:00 2001 From: Jacob Lund Date: Mon, 8 Jul 2024 14:06:43 +0930 Subject: [PATCH 01/16] Adds actual windows support for streaming bgra frames to the flutter client --- .../camera_windows/lib/camera_windows.dart | 60 ++++++++++++ .../camera_windows/lib/type_conversion.dart | 25 +++++ .../camera/camera_windows/windows/camera.h | 2 + .../camera_windows/windows/camera_plugin.cpp | 97 ++++++++++++++++++- .../camera_windows/windows/camera_plugin.h | 9 +- .../windows/capture_controller.cpp | 41 +++++++- .../windows/capture_controller.h | 8 +- .../camera_windows/windows/test/mocks.h | 7 ++ 8 files changed, 244 insertions(+), 5 deletions(-) create mode 100644 packages/camera/camera_windows/lib/type_conversion.dart diff --git a/packages/camera/camera_windows/lib/camera_windows.dart b/packages/camera/camera_windows/lib/camera_windows.dart index fc4ce3b09c81..4d22e27edfa0 100644 --- a/packages/camera/camera_windows/lib/camera_windows.dart +++ b/packages/camera/camera_windows/lib/camera_windows.dart @@ -6,6 +6,7 @@ import 'dart:async'; import 'dart:math'; import 'package:camera_platform_interface/camera_platform_interface.dart'; +import 'package:camera_windows/type_conversion.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:stream_transform/stream_transform.dart'; @@ -25,6 +26,12 @@ class CameraWindows extends CameraPlatform { /// Camera specific method channels to allow communicating with specific cameras. final Map _cameraChannels = {}; + // The stream to receive frames from the native code. + StreamSubscription? _platformImageStreamSubscription; + + // The stream for vending frames to platform interface clients. + StreamController? _frameStreamController; + /// The controller that broadcasts events coming from handleCameraMethodCall /// /// It is a `broadcast` because multiple controllers will connect to @@ -277,6 +284,59 @@ class CameraWindows extends CameraPlatform { 'resumeVideoRecording() is not supported due to Win32 API limitations.'); } + @override + Stream onStreamedFrameAvailable(int cameraId, + {CameraImageStreamOptions? options}) { + _installStreamController( + onListen: () => _onFrameStreamListen(cameraId), + onCancel: () => _onFrameStreamCancel(cameraId)); + return _frameStreamController!.stream; + } + + StreamController _installStreamController( + {void Function()? onListen, void Function()? onCancel}) { + _frameStreamController = StreamController( + onListen: onListen ?? () {}, + onPause: _onFrameStreamPauseResume, + onResume: _onFrameStreamPauseResume, + onCancel: onCancel ?? () {}, + ); + return _frameStreamController!; + } + + void _onFrameStreamListen(int cameraId) { + _startPlatformStream(cameraId); + } + + Future _startPlatformStream(int cameraId) async { + _startStreamListener(); + await pluginChannel.invokeMethod( + 'startImageStream', {'cameraId': cameraId}); + } + + void _startStreamListener() { + const EventChannel cameraEventChannel = + EventChannel('plugins.flutter.io/camera_android/imageStream'); + _platformImageStreamSubscription = + cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { + _frameStreamController! + .add(cameraImageFromPlatformData(imageData as Map)); + }); + } + + FutureOr _onFrameStreamCancel(int cameraId) async { + await pluginChannel.invokeMethod( + 'stopImageStream', {'cameraId': cameraId}); + await _platformImageStreamSubscription?.cancel(); + _platformImageStreamSubscription = null; + _frameStreamController = null; + } + + void _onFrameStreamPauseResume() { + throw CameraException('InvalidCall', + 'Pause and resume are not supported for onStreamedFrameAvailable'); + } + @override Future setFlashMode(int cameraId, FlashMode mode) async { // TODO(jokerttu): Implement flash mode support, https://github.com/flutter/flutter/issues/97537. diff --git a/packages/camera/camera_windows/lib/type_conversion.dart b/packages/camera/camera_windows/lib/type_conversion.dart new file mode 100644 index 000000000000..10cf3db8c4f5 --- /dev/null +++ b/packages/camera/camera_windows/lib/type_conversion.dart @@ -0,0 +1,25 @@ +// 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 data) { + return CameraImageData( + format: const CameraImageFormat(ImageFormatGroup.bgra8888, raw: 0), + 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: [ + CameraImagePlane( + bytes: data['data'] as Uint8List, + bytesPerRow: ((data['width'] as int) * 4), + ) + ]); +} diff --git a/packages/camera/camera_windows/windows/camera.h b/packages/camera/camera_windows/windows/camera.h index 50ec6a75e74b..823723e4e0c7 100644 --- a/packages/camera/camera_windows/windows/camera.h +++ b/packages/camera/camera_windows/windows/camera.h @@ -27,6 +27,8 @@ enum class PendingResultType { kTakePicture, kStartRecord, kStopRecord, + kStartStream, + kStopStream, kPausePreview, kResumePreview, }; diff --git a/packages/camera/camera_windows/windows/camera_plugin.cpp b/packages/camera/camera_windows/windows/camera_plugin.cpp index c99565dd49c8..4f15de2551f2 100644 --- a/packages/camera/camera_windows/windows/camera_plugin.cpp +++ b/packages/camera/camera_windows/windows/camera_plugin.cpp @@ -6,8 +6,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -18,6 +20,8 @@ #include #include +#include + #include "capture_device_info.h" #include "com_heap_ptr.h" #include "string_utils.h" @@ -31,6 +35,7 @@ namespace { // Channel events constexpr char kChannelName[] = "plugins.flutter.io/camera_windows"; +constexpr char kFrameEventChannelName[] = "plugins.flutter.io/camera_android/imageStream"; constexpr char kAvailableCamerasMethod[] = "availableCameras"; constexpr char kCreateMethod[] = "create"; @@ -38,6 +43,9 @@ constexpr char kInitializeMethod[] = "initialize"; constexpr char kTakePictureMethod[] = "takePicture"; constexpr char kStartVideoRecordingMethod[] = "startVideoRecording"; constexpr char kStopVideoRecordingMethod[] = "stopVideoRecording"; +constexpr char kStartImageStreamingMethod[] = "startImageStream"; +constexpr char kStopImageStreamingMethod[] = "stopImageStream"; + constexpr char kPausePreview[] = "pausePreview"; constexpr char kResumePreview[] = "resumePreview"; constexpr char kDisposeMethod[] = "dispose"; @@ -62,6 +70,8 @@ constexpr char kResolutionPresetValueMax[] = "max"; const std::string kPictureCaptureExtension = "jpeg"; const std::string kVideoCaptureExtension = "mp4"; +std::unique_ptr> event_sink; + // Looks for |key| in |map|, returning the associated value if it is present, or // a nullptr if not. const EncodableValue* ValueOrNull(const EncodableMap& map, const char* key) { @@ -198,6 +208,9 @@ void CameraPlugin::RegisterWithRegistrar( auto channel = std::make_unique>( registrar->messenger(), kChannelName, &flutter::StandardMethodCodec::GetInstance()); + auto frameEventchannel = std::make_unique>( + registrar->messenger(), kFrameEventChannelName, + &flutter::StandardMethodCodec::GetInstance()); std::unique_ptr plugin = std::make_unique( registrar->texture_registrar(), registrar->messenger()); @@ -206,6 +219,16 @@ void CameraPlugin::RegisterWithRegistrar( [plugin_pointer = plugin.get()](const auto& call, auto result) { plugin_pointer->HandleMethodCall(call, std::move(result)); }); + auto event_channel_handler = std::make_unique>( + [](auto arguments, auto events) { + event_sink = std::move(events); + return nullptr; + }, + [](auto arguments) { + event_sink.reset(); + return nullptr; + }); + frameEventchannel->SetStreamHandler(std::move(event_channel_handler)); registrar->AddPlugin(std::move(plugin)); } @@ -262,7 +285,19 @@ void CameraPlugin::HandleMethodCall( assert(arguments); return StopVideoRecordingMethodHandler(*arguments, std::move(result)); - } else if (method_name.compare(kPausePreview) == 0) { + } else if (method_name.compare(kStartImageStreamingMethod) == 0) { + const auto* arguments = + std::get_if(method_call.arguments()); + assert(arguments); + + return StartImageStreamingMethodHandler(*arguments, std::move(result)); + }else if (method_name.compare(kStopImageStreamingMethod) == 0) { + const auto* arguments = + std::get_if(method_call.arguments()); + assert(arguments); + + return StopImageStreamingMethodHandler(*arguments, std::move(result)); + }else if (method_name.compare(kPausePreview) == 0) { const auto* arguments = std::get_if(method_call.arguments()); assert(arguments); @@ -569,6 +604,66 @@ void CameraPlugin::StopVideoRecordingMethodHandler( cc->StopRecord(); } } +void CameraPlugin::StartImageStreamingMethodHandler( + const EncodableMap& args, std::unique_ptr> result) { + auto camera_id = GetInt64ValueOrNull(args, kCameraIdKey); //get camera id + if (!camera_id) { + return result->Error("argument_error", + std::string(kCameraIdKey) + " missing"); + } + //check if request already exists + auto camera = GetCameraByCameraId(*camera_id); + if (!camera) { + return result->Error("camera_error", "Camera not created"); + } + if (camera->HasPendingResultByType(PendingResultType::kStartStream)) { + return result->Error("camera_error", + "Pending start stream request exists"); + } + + if (!event_sink) { + return result->Error("camera_error", + "Unable to make event channel from windows"); + } + + if (camera->AddPendingResult(PendingResultType::kStartStream, + std::move(result))) { + auto cc = camera->GetCaptureController(); + assert(cc); + cc->StartImageStream(std::move(event_sink)); + } + + +} +void CameraPlugin::StopImageStreamingMethodHandler( + const EncodableMap& args, std::unique_ptr> result) { + auto camera_id = GetInt64ValueOrNull(args, kCameraIdKey); //get camera id + if (!camera_id) { + return result->Error("argument_error", + std::string(kCameraIdKey) + " missing"); + } + //check if request already exists + auto camera = GetCameraByCameraId(*camera_id); + if (!camera) { + return result->Error("camera_error", "Camera not created"); + } + if (camera->HasPendingResultByType(PendingResultType::kStartStream)) { + return result->Error("camera_error", + "Pending start stream request exists"); + } + + if (!event_sink) { + return result->Error("camera_error", + "Unable to make event channel from windows"); + } + + if (camera->AddPendingResult(PendingResultType::kStartStream, + std::move(result))) { + auto cc = camera->GetCaptureController(); + assert(cc); + cc->StopImageStream(); + } +} void CameraPlugin::TakePictureMethodHandler( const EncodableMap& args, std::unique_ptr> result) { diff --git a/packages/camera/camera_windows/windows/camera_plugin.h b/packages/camera/camera_windows/windows/camera_plugin.h index 1baa2477beb5..53b57bcf7ed3 100644 --- a/packages/camera/camera_windows/windows/camera_plugin.h +++ b/packages/camera/camera_windows/windows/camera_plugin.h @@ -7,9 +7,11 @@ #include #include +#include #include #include + #include #include "camera.h" @@ -101,7 +103,12 @@ class CameraPlugin : public flutter::Plugin, // Stores result object to be handled after request is processed. void StopVideoRecordingMethodHandler(const EncodableMap& args, std::unique_ptr> result); - + // Handles StartImageStreaming method calls. + void StartImageStreamingMethodHandler(const EncodableMap& args, + std::unique_ptr> result); + // Handles StopImageStreaming method calls. + void StopImageStreamingMethodHandler(const EncodableMap& args, + std::unique_ptr> result); // Handles pausePreview method calls. // Requests existing camera controller to pause recording. // Stores result object to be handled after request is processed. diff --git a/packages/camera/camera_windows/windows/capture_controller.cpp b/packages/camera/camera_windows/windows/capture_controller.cpp index 0c06f69a4a4a..5d06f2c5a324 100644 --- a/packages/camera/camera_windows/windows/capture_controller.cpp +++ b/packages/camera/camera_windows/windows/capture_controller.cpp @@ -11,6 +11,8 @@ #include #include +#include + #include "com_heap_ptr.h" #include "photo_handler.h" #include "preview_handler.h" @@ -18,6 +20,10 @@ #include "string_utils.h" #include "texture_handler.h" +#include +#include + + namespace camera_windows { using Microsoft::WRL::ComPtr; @@ -561,6 +567,15 @@ void CaptureControllerImpl::StopRecord() { "Failed to stop video recording"); } } +void CaptureControllerImpl::StartImageStream(std::unique_ptr> sink) { + assert(capture_controller_listener_); + image_stream_sink_ = std::move(sink); +} + +void CaptureControllerImpl::StopImageStream() { + assert(capture_controller_listener_); + image_stream_sink_.reset(); +} // Stops timed recording. Called internally when requested time is passed. // Check MF_CAPTURE_ENGINE_RECORD_STOPPED event handling for response process. @@ -878,8 +893,30 @@ bool CaptureControllerImpl::UpdateBuffer(uint8_t* buffer, if (!texture_handler_) { return false; } - return texture_handler_->UpdateBuffer(buffer, data_length); -} + if (image_stream_sink_) { + // Convert the buffer data to a std::vector + std::vector buffer_data(buffer, buffer + data_length); + + // Ensure preview_frame_height_ and preview_frame_width_ are of supported types + int preview_frame_height = static_cast(preview_frame_height_); + int preview_frame_width = static_cast(preview_frame_width_); + + // Create a map to hold the buffer data and data length + flutter::EncodableMap data_map; + data_map[flutter::EncodableValue("data")] = flutter::EncodableValue(buffer_data); + data_map[flutter::EncodableValue("height")] = flutter::EncodableValue(preview_frame_height); + data_map[flutter::EncodableValue("width")] = flutter::EncodableValue(preview_frame_width); + data_map[flutter::EncodableValue("length")] = flutter::EncodableValue(static_cast(data_length)); + + // Wrap the map in a flutter::EncodableValue + flutter::EncodableValue encoded_value(data_map); + + // Send the encoded value through the image_stream_sink_ + image_stream_sink_->Success(encoded_value); + } + return texture_handler_->UpdateBuffer(buffer, data_length); + + } // Handles capture time update from each processed frame. // Stops timed recordings if requested recording duration has passed. diff --git a/packages/camera/camera_windows/windows/capture_controller.h b/packages/camera/camera_windows/windows/capture_controller.h index c6807002e589..ef5e091f3dad 100644 --- a/packages/camera/camera_windows/windows/capture_controller.h +++ b/packages/camera/camera_windows/windows/capture_controller.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -113,6 +114,9 @@ class CaptureController { // Stops the current video recording. virtual void StopRecord() = 0; + virtual void StartImageStream(std::unique_ptr> sink) = 0; + virtual void StopImageStream() = 0; + // Captures a still photo. virtual void TakePicture(const std::string& file_path) = 0; }; @@ -148,6 +152,8 @@ class CaptureControllerImpl : public CaptureController, void StartRecord(const std::string& file_path, int64_t max_video_duration_ms) override; void StopRecord() override; + void StartImageStream(std::unique_ptr> sink) override; + void StopImageStream() override; void TakePicture(const std::string& file_path) override; // CaptureEngineObserver @@ -242,8 +248,8 @@ class CaptureControllerImpl : public CaptureController, std::unique_ptr preview_handler_; std::unique_ptr photo_handler_; std::unique_ptr texture_handler_; + std::unique_ptr> image_stream_sink_; CaptureControllerListener* capture_controller_listener_; - std::string video_device_id_; CaptureEngineState capture_engine_state_ = CaptureEngineState::kNotInitialized; diff --git a/packages/camera/camera_windows/windows/test/mocks.h b/packages/camera/camera_windows/windows/test/mocks.h index 1f71a0e4d5dc..ddeb0a767fa3 100644 --- a/packages/camera/camera_windows/windows/test/mocks.h +++ b/packages/camera/camera_windows/windows/test/mocks.h @@ -251,6 +251,10 @@ class MockCaptureController : public CaptureController { (const std::string& file_path, int64_t max_video_duration_ms), (override)); MOCK_METHOD(void, StopRecord, (), (override)); + MOCK_METHOD(void, StartImageStream, + (std::unique_ptr> sink), + (override)); + MOCK_METHOD(void, StopImageStream, (), (override)); MOCK_METHOD(void, TakePicture, (const std::string& file_path), (override)); }; @@ -1024,6 +1028,9 @@ class MockCaptureEngine : public IMFCaptureEngine { MOCK_METHOD(HRESULT, StartPreview, ()); MOCK_METHOD(HRESULT, StopPreview, ()); MOCK_METHOD(HRESULT, StartRecord, ()); + MOCK_METHOD(HRESULT, StartImageStream, ()); + MOCK_METHOD(HRESULT, StopImageStream, ()); + MOCK_METHOD(HRESULT, StopRecord, (BOOL finalize, BOOL flushUnprocessedSamples)); MOCK_METHOD(HRESULT, TakePhoto, ()); From 99ae0e4356dd532403c639f11c84ccc80ff58239 Mon Sep 17 00:00:00 2001 From: Jacob Lund Date: Mon, 8 Jul 2024 14:10:09 +0930 Subject: [PATCH 02/16] add windows as an option for streaming frames --- packages/camera/camera/lib/src/camera_controller.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/camera/camera/lib/src/camera_controller.dart b/packages/camera/camera/lib/src/camera_controller.dart index 5f90a0a740a9..f9b797d459d7 100644 --- a/packages/camera/camera/lib/src/camera_controller.dart +++ b/packages/camera/camera/lib/src/camera_controller.dart @@ -486,7 +486,8 @@ class CameraController extends ValueNotifier { // TODO(bmparr): Add settings for resolution and fps. Future startImageStream(onLatestImageAvailable onAvailable) async { assert(defaultTargetPlatform == TargetPlatform.android || - defaultTargetPlatform == TargetPlatform.iOS); + defaultTargetPlatform == TargetPlatform.iOS || + defaultTargetPlatform == TargetPlatform.windows); _throwIfNotInitialized('startImageStream'); if (value.isRecordingVideo) { throw CameraException( From a89cf54b74867621a4d377817ac605456e5293a5 Mon Sep 17 00:00:00 2001 From: Jacob Lund Date: Wed, 10 Jul 2024 08:19:22 +0930 Subject: [PATCH 03/16] apply suggested format changes --- .../camera_windows/lib/camera_windows.dart | 3 +- .../camera_windows/lib/type_conversion.dart | 4 +- .../camera_windows/windows/camera_plugin.cpp | 17 ++++---- .../windows/capture_controller.cpp | 40 +++++++++---------- .../windows/capture_controller.h | 5 ++- 5 files changed, 36 insertions(+), 33 deletions(-) diff --git a/packages/camera/camera_windows/lib/camera_windows.dart b/packages/camera/camera_windows/lib/camera_windows.dart index 4d22e27edfa0..4f9dd084d6d1 100644 --- a/packages/camera/camera_windows/lib/camera_windows.dart +++ b/packages/camera/camera_windows/lib/camera_windows.dart @@ -6,11 +6,12 @@ import 'dart:async'; import 'dart:math'; import 'package:camera_platform_interface/camera_platform_interface.dart'; -import 'package:camera_windows/type_conversion.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:stream_transform/stream_transform.dart'; +import 'type_conversion.dart'; + /// An implementation of [CameraPlatform] for Windows. class CameraWindows extends CameraPlatform { /// Registers the Windows implementation of CameraPlatform. diff --git a/packages/camera/camera_windows/lib/type_conversion.dart b/packages/camera/camera_windows/lib/type_conversion.dart index 10cf3db8c4f5..ed24a752341a 100644 --- a/packages/camera/camera_windows/lib/type_conversion.dart +++ b/packages/camera/camera_windows/lib/type_conversion.dart @@ -16,10 +16,10 @@ CameraImageData cameraImageFromPlatformData(Map data) { lensAperture: data['lensAperture'] as double?, sensorExposureTime: data['sensorExposureTime'] as int?, sensorSensitivity: data['sensorSensitivity'] as double?, - planes: [ + planes: [ CameraImagePlane( bytes: data['data'] as Uint8List, - bytesPerRow: ((data['width'] as int) * 4), + bytesPerRow: (data['width'] as int) * 4, ) ]); } diff --git a/packages/camera/camera_windows/windows/camera_plugin.cpp b/packages/camera/camera_windows/windows/camera_plugin.cpp index 4f15de2551f2..1e46c1b9d014 100644 --- a/packages/camera/camera_windows/windows/camera_plugin.cpp +++ b/packages/camera/camera_windows/windows/camera_plugin.cpp @@ -291,18 +291,18 @@ void CameraPlugin::HandleMethodCall( assert(arguments); return StartImageStreamingMethodHandler(*arguments, std::move(result)); - }else if (method_name.compare(kStopImageStreamingMethod) == 0) { + } else if (method_name.compare(kStopImageStreamingMethod) == 0) { const auto* arguments = std::get_if(method_call.arguments()); assert(arguments); return StopImageStreamingMethodHandler(*arguments, std::move(result)); - }else if (method_name.compare(kPausePreview) == 0) { - const auto* arguments = - std::get_if(method_call.arguments()); - assert(arguments); + } else if (method_name.compare(kPausePreview) == 0) { + const auto* arguments = + std::get_if(method_call.arguments()); + assert(arguments); - return PausePreviewMethodHandler(*arguments, std::move(result)); + return PausePreviewMethodHandler(*arguments, std::move(result)); } else if (method_name.compare(kResumePreview) == 0) { const auto* arguments = std::get_if(method_call.arguments()); @@ -606,7 +606,7 @@ void CameraPlugin::StopVideoRecordingMethodHandler( } void CameraPlugin::StartImageStreamingMethodHandler( const EncodableMap& args, std::unique_ptr> result) { - auto camera_id = GetInt64ValueOrNull(args, kCameraIdKey); //get camera id + auto camera_id = GetInt64ValueOrNull(args, kCameraIdKey); if (!camera_id) { return result->Error("argument_error", std::string(kCameraIdKey) + " missing"); @@ -632,9 +632,8 @@ void CameraPlugin::StartImageStreamingMethodHandler( assert(cc); cc->StartImageStream(std::move(event_sink)); } - - } + void CameraPlugin::StopImageStreamingMethodHandler( const EncodableMap& args, std::unique_ptr> result) { auto camera_id = GetInt64ValueOrNull(args, kCameraIdKey); //get camera id diff --git a/packages/camera/camera_windows/windows/capture_controller.cpp b/packages/camera/camera_windows/windows/capture_controller.cpp index 5d06f2c5a324..31c3d4251b7e 100644 --- a/packages/camera/camera_windows/windows/capture_controller.cpp +++ b/packages/camera/camera_windows/windows/capture_controller.cpp @@ -5,12 +5,13 @@ #include "capture_controller.h" #include +#include +#include #include #include #include #include - #include #include "com_heap_ptr.h" @@ -20,8 +21,7 @@ #include "string_utils.h" #include "texture_handler.h" -#include -#include + namespace camera_windows { @@ -894,29 +894,29 @@ bool CaptureControllerImpl::UpdateBuffer(uint8_t* buffer, return false; } if (image_stream_sink_) { - // Convert the buffer data to a std::vector - std::vector buffer_data(buffer, buffer + data_length); + // Convert the buffer data to a std::vector. + std::vector buffer_data(buffer, buffer + data_length); - // Ensure preview_frame_height_ and preview_frame_width_ are of supported types - int preview_frame_height = static_cast(preview_frame_height_); - int preview_frame_width = static_cast(preview_frame_width_); + // Ensure preview_frame_height_ and preview_frame_width_ are of supported types. + int preview_frame_height = static_cast(preview_frame_height_); + int preview_frame_width = static_cast(preview_frame_width_); - // Create a map to hold the buffer data and data length - flutter::EncodableMap data_map; - data_map[flutter::EncodableValue("data")] = flutter::EncodableValue(buffer_data); - data_map[flutter::EncodableValue("height")] = flutter::EncodableValue(preview_frame_height); - data_map[flutter::EncodableValue("width")] = flutter::EncodableValue(preview_frame_width); - data_map[flutter::EncodableValue("length")] = flutter::EncodableValue(static_cast(data_length)); + // Create a map to hold the buffer data and data length. + flutter::EncodableMap data_map; + data_map[flutter::EncodableValue("data")] = flutter::EncodableValue(buffer_data); + data_map[flutter::EncodableValue("height")] = flutter::EncodableValue(preview_frame_height); + data_map[flutter::EncodableValue("width")] = flutter::EncodableValue(preview_frame_width); + data_map[flutter::EncodableValue("length")] = flutter::EncodableValue(static_cast(data_length)); - // Wrap the map in a flutter::EncodableValue - flutter::EncodableValue encoded_value(data_map); + // Wrap the map in a flutter::EncodableValue. + flutter::EncodableValue encoded_value(data_map); - // Send the encoded value through the image_stream_sink_ - image_stream_sink_->Success(encoded_value); + // Send the encoded value through the image_stream_sink_. + image_stream_sink_->Success(encoded_value); } - return texture_handler_->UpdateBuffer(buffer, data_length); + return texture_handler_->UpdateBuffer(buffer, data_length); - } +} // Handles capture time update from each processed frame. // Stops timed recordings if requested recording duration has passed. diff --git a/packages/camera/camera_windows/windows/capture_controller.h b/packages/camera/camera_windows/windows/capture_controller.h index ef5e091f3dad..20e3f4dd029e 100644 --- a/packages/camera/camera_windows/windows/capture_controller.h +++ b/packages/camera/camera_windows/windows/capture_controller.h @@ -6,6 +6,7 @@ #define PACKAGES_CAMERA_CAMERA_WINDOWS_WINDOWS_CAPTURE_CONTROLLER_H_ #include +#include #include #include #include @@ -13,7 +14,6 @@ #include #include #include -#include #include #include @@ -114,7 +114,10 @@ class CaptureController { // Stops the current video recording. virtual void StopRecord() = 0; + // Starts image streaming. virtual void StartImageStream(std::unique_ptr> sink) = 0; + + // Stops the current image streaming. virtual void StopImageStream() = 0; // Captures a still photo. From 20c61924c80a00ac07057f0d276184a2d120580d Mon Sep 17 00:00:00 2001 From: Jacob Lund Date: Wed, 10 Jul 2024 08:30:33 +0930 Subject: [PATCH 04/16] change to explict types --- .../camera/camera_windows/windows/camera_plugin.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/camera/camera_windows/windows/camera_plugin.cpp b/packages/camera/camera_windows/windows/camera_plugin.cpp index 1e46c1b9d014..75785d864b40 100644 --- a/packages/camera/camera_windows/windows/camera_plugin.cpp +++ b/packages/camera/camera_windows/windows/camera_plugin.cpp @@ -606,13 +606,13 @@ void CameraPlugin::StopVideoRecordingMethodHandler( } void CameraPlugin::StartImageStreamingMethodHandler( const EncodableMap& args, std::unique_ptr> result) { - auto camera_id = GetInt64ValueOrNull(args, kCameraIdKey); + std::optional camera_id = GetInt64ValueOrNull(args, kCameraIdKey); if (!camera_id) { return result->Error("argument_error", std::string(kCameraIdKey) + " missing"); } //check if request already exists - auto camera = GetCameraByCameraId(*camera_id); + Camera* camera = GetCameraByCameraId(*camera_id); if (!camera) { return result->Error("camera_error", "Camera not created"); } @@ -628,7 +628,7 @@ void CameraPlugin::StartImageStreamingMethodHandler( if (camera->AddPendingResult(PendingResultType::kStartStream, std::move(result))) { - auto cc = camera->GetCaptureController(); + CaptureController* cc = camera->GetCaptureController(); assert(cc); cc->StartImageStream(std::move(event_sink)); } @@ -636,13 +636,13 @@ void CameraPlugin::StartImageStreamingMethodHandler( void CameraPlugin::StopImageStreamingMethodHandler( const EncodableMap& args, std::unique_ptr> result) { - auto camera_id = GetInt64ValueOrNull(args, kCameraIdKey); //get camera id + std::optional camera_id = GetInt64ValueOrNull(args, kCameraIdKey); //get camera id if (!camera_id) { return result->Error("argument_error", std::string(kCameraIdKey) + " missing"); } //check if request already exists - auto camera = GetCameraByCameraId(*camera_id); + Camera* camera = GetCameraByCameraId(*camera_id); if (!camera) { return result->Error("camera_error", "Camera not created"); } @@ -658,7 +658,7 @@ void CameraPlugin::StopImageStreamingMethodHandler( if (camera->AddPendingResult(PendingResultType::kStartStream, std::move(result))) { - auto cc = camera->GetCaptureController(); + CaptureController* cc = camera->GetCaptureController(); assert(cc); cc->StopImageStream(); } From d48c932b6452d260ed4d0220a03e0635a1d2e23a Mon Sep 17 00:00:00 2001 From: Jacob Lund Date: Wed, 10 Jul 2024 11:09:42 +0930 Subject: [PATCH 05/16] Migrated streaming to pigeon --- .../camera_windows/lib/camera_windows.dart | 6 +- .../camera_windows/windows/camera_plugin.cpp | 74 +++++++ .../camera_windows/windows/camera_plugin.h | 6 + .../camera_windows/windows/messages.g.cpp | 180 ++++++++++++++---- .../camera_windows/windows/messages.g.h | 113 ++++++----- 5 files changed, 290 insertions(+), 89 deletions(-) diff --git a/packages/camera/camera_windows/lib/camera_windows.dart b/packages/camera/camera_windows/lib/camera_windows.dart index a5a1a4521aff..72358d047b75 100644 --- a/packages/camera/camera_windows/lib/camera_windows.dart +++ b/packages/camera/camera_windows/lib/camera_windows.dart @@ -275,8 +275,7 @@ class CameraWindows extends CameraPlatform { Future _startPlatformStream(int cameraId) async { _startStreamListener(); - await pluginChannel.invokeMethod( - 'startImageStream', {'cameraId': cameraId}); + await _hostApi.startImageStream(cameraId); } void _startStreamListener() { @@ -290,8 +289,7 @@ class CameraWindows extends CameraPlatform { } FutureOr _onFrameStreamCancel(int cameraId) async { - await pluginChannel.invokeMethod( - 'stopImageStream', {'cameraId': cameraId}); + await _hostApi.stopImageStream(cameraId); await _platformImageStreamSubscription?.cancel(); _platformImageStreamSubscription = null; _frameStreamController = null; diff --git a/packages/camera/camera_windows/windows/camera_plugin.cpp b/packages/camera/camera_windows/windows/camera_plugin.cpp index 5bbc951956a6..e738b3930fd2 100644 --- a/packages/camera/camera_windows/windows/camera_plugin.cpp +++ b/packages/camera/camera_windows/windows/camera_plugin.cpp @@ -4,6 +4,8 @@ #include "camera_plugin.h" +#include +#include #include #include #include @@ -32,6 +34,10 @@ namespace { const std::string kPictureCaptureExtension = "jpeg"; const std::string kVideoCaptureExtension = "mp4"; +constexpr char kFrameEventChannelName[] = + "plugins.flutter.io/camera_android/imageStream"; + +std::unique_ptr> event_sink; // Builds CaptureDeviceInfo object from given device holding device name and id. std::unique_ptr GetDeviceInfo(IMFActivate* device) { @@ -122,6 +128,22 @@ void CameraPlugin::RegisterWithRegistrar( std::unique_ptr plugin = std::make_unique( registrar->texture_registrar(), registrar->messenger()); + auto frameEventchannel = std::make_unique>( + registrar->messenger(), kFrameEventChannelName, + &flutter::StandardMethodCodec::GetInstance()); + + auto event_channel_handler = + std::make_unique>( + [](auto arguments, auto events) { + event_sink = std::move(events); + return nullptr; + }, + [](auto arguments) { + event_sink.reset(); + return nullptr; + }); + frameEventchannel->SetStreamHandler(std::move(event_channel_handler)); + CameraApi::SetUp(registrar->messenger(), plugin.get()); registrar->AddPlugin(std::move(plugin)); @@ -349,6 +371,58 @@ void CameraPlugin::StopVideoRecording( } } +void CameraPlugin::StartImageStream( + int64_t camera_id, + std::function reply)> result) { + // check if request already exists + Camera* camera = GetCameraByCameraId(camera_id); + if (!camera) { + return result(FlutterError("camera_error", "Camera not created")); + } + if (camera->HasPendingResultByType(PendingResultType::kStartStream)) { + return result( + FlutterError("camera_error", "Pending start stream request exists")); + } + + if (!event_sink) { + return result(FlutterError("camera_error", + "Unable to make event channel from windows")); + } + + if (camera->AddPendingVoidResult(PendingResultType::kStartStream, + std::move(result))) { + CaptureController* cc = camera->GetCaptureController(); + assert(cc); + cc->StartImageStream(std::move(event_sink)); + } +} + +void CameraPlugin::StopImageStream( + int64_t camera_id, + std::function reply)> result) { + // check if request already exists + Camera* camera = GetCameraByCameraId(camera_id); + if (!camera) { + return result(FlutterError("camera_error", "Camera not created")); + } + if (camera->HasPendingResultByType(PendingResultType::kStartStream)) { + return result( + FlutterError("camera_error", "Pending start stream request exists")); + } + + if (!event_sink) { + return result(FlutterError("camera_error", + "Unable to make event channel from windows")); + } + + if (camera->AddPendingVoidResult(PendingResultType::kStartStream, + std::move(result))) { + CaptureController* cc = camera->GetCaptureController(); + assert(cc); + cc->StopImageStream(); + } +} + void CameraPlugin::TakePicture( int64_t camera_id, std::function reply)> result) { auto camera = GetCameraByCameraId(camera_id); diff --git a/packages/camera/camera_windows/windows/camera_plugin.h b/packages/camera/camera_windows/windows/camera_plugin.h index 43f0e3a4619d..74f598ba6457 100644 --- a/packages/camera/camera_windows/windows/camera_plugin.h +++ b/packages/camera/camera_windows/windows/camera_plugin.h @@ -68,6 +68,12 @@ class CameraPlugin : public flutter::Plugin, void StopVideoRecording( int64_t camera_id, std::function reply)> result) override; + void StartImageStream( + int64_t camera_id, + std::function reply)> result) override; + void StopImageStream( + int64_t camera_id, + std::function reply)> result) override; void TakePicture( int64_t camera_id, std::function reply)> result) override; diff --git a/packages/camera/camera_windows/windows/messages.g.cpp b/packages/camera/camera_windows/windows/messages.g.cpp index 10741fa13855..2838e7b242c8 100644 --- a/packages/camera/camera_windows/windows/messages.g.cpp +++ b/packages/camera/camera_windows/windows/messages.g.cpp @@ -481,59 +481,155 @@ void CameraApi::SetUp(flutter::BinaryMessenger* binary_messenger, } } { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.camera_windows.CameraApi.startImageStream" + prepended_suffix, &GetCodec()); + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.camera_windows.CameraApi.startVideoRecording" + + prepended_suffix, + &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_camera_id_arg = args.at(0); - if (encodable_camera_id_arg.IsNull()) { - reply(WrapError("camera_id_arg unexpectedly null.")); - return; - } - const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); - api->StartImageStream(camera_id_arg, [reply](std::optional&& output) { - if (output.has_value()) { - reply(WrapError(output.value())); - return; + channel.SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_camera_id_arg = args.at(0); + if (encodable_camera_id_arg.IsNull()) { + reply(WrapError("camera_id_arg unexpectedly null.")); + return; + } + const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); + const auto& encodable_options_arg = args.at(1); + if (encodable_options_arg.IsNull()) { + reply(WrapError("options_arg unexpectedly null.")); + return; + } + const auto& options_arg = + std::any_cast( + std::get(encodable_options_arg)); + api->StartVideoRecording( + camera_id_arg, options_arg, + [reply](std::optional&& output) { + if (output.has_value()) { + reply(WrapError(output.value())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.camera_windows.CameraApi.stopImageStream" + prepended_suffix, &GetCodec()); + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.camera_windows.CameraApi.stopVideoRecording" + + prepended_suffix, + &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_camera_id_arg = args.at(0); - if (encodable_camera_id_arg.IsNull()) { - reply(WrapError("camera_id_arg unexpectedly null.")); - return; - } - const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); - api->StopImageStream(camera_id_arg, [reply](std::optional&& output) { - if (output.has_value()) { - reply(WrapError(output.value())); - return; + channel.SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_camera_id_arg = args.at(0); + if (encodable_camera_id_arg.IsNull()) { + reply(WrapError("camera_id_arg unexpectedly null.")); + return; + } + const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); + api->StopVideoRecording( + camera_id_arg, [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back( + EncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } + { + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.camera_windows.CameraApi.startImageStream" + + prepended_suffix, + &GetCodec()); + if (api != nullptr) { + channel.SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_camera_id_arg = args.at(0); + if (encodable_camera_id_arg.IsNull()) { + reply(WrapError("camera_id_arg unexpectedly null.")); + return; + } + const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); + api->StartImageStream( + camera_id_arg, [reply](std::optional&& output) { + if (output.has_value()) { + reply(WrapError(output.value())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } + { + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.camera_windows.CameraApi.stopImageStream" + + prepended_suffix, + &GetCodec()); + if (api != nullptr) { + channel.SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_camera_id_arg = args.at(0); + if (encodable_camera_id_arg.IsNull()) { + reply(WrapError("camera_id_arg unexpectedly null.")); + return; + } + const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); + api->StopImageStream( + camera_id_arg, [reply](std::optional&& output) { + if (output.has_value()) { + reply(WrapError(output.value())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); } else { channel.SetMessageHandler(nullptr); } diff --git a/packages/camera/camera_windows/windows/messages.g.h b/packages/camera/camera_windows/windows/messages.g.h index e2ee53253fff..772aa3c6200d 100644 --- a/packages/camera/camera_windows/windows/messages.g.h +++ b/packages/camera/camera_windows/windows/messages.g.h @@ -17,16 +17,17 @@ namespace camera_windows { + // Generated class from Pigeon. class FlutterError { public: - explicit FlutterError(const std::string& code) : code_(code) {} + explicit FlutterError(const std::string& code) + : code_(code) {} explicit FlutterError(const std::string& code, const std::string& message) - : code_(code), message_(message) {} - explicit FlutterError(const std::string& code, const std::string& message, - const flutter::EncodableValue& details) - : code_(code), message_(message), details_(details) {} + : code_(code), message_(message) {} + explicit FlutterError(const std::string& code, const std::string& message, const flutter::EncodableValue& details) + : code_(code), message_(message), details_(details) {} const std::string& code() const { return code_; } const std::string& message() const { return message_; } @@ -38,8 +39,7 @@ class FlutterError { flutter::EncodableValue details_; }; -template -class ErrorOr { +template class ErrorOr { public: ErrorOr(const T& rhs) : v_(rhs) {} ErrorOr(const T&& rhs) : v_(std::move(rhs)) {} @@ -58,6 +58,7 @@ class ErrorOr { std::variant v_; }; + // Pigeon version of platform interface's ResolutionPreset. enum class PlatformResolutionPreset { low = 0, @@ -75,13 +76,16 @@ class PlatformMediaSettings { public: // Constructs an object setting all non-nullable fields. explicit PlatformMediaSettings( - const PlatformResolutionPreset& resolution_preset, bool enable_audio); + const PlatformResolutionPreset& resolution_preset, + bool enable_audio); // Constructs an object setting all fields. explicit PlatformMediaSettings( - const PlatformResolutionPreset& resolution_preset, - const int64_t* frames_per_second, const int64_t* video_bitrate, - const int64_t* audio_bitrate, bool enable_audio); + const PlatformResolutionPreset& resolution_preset, + const int64_t* frames_per_second, + const int64_t* video_bitrate, + const int64_t* audio_bitrate, + bool enable_audio); const PlatformResolutionPreset& resolution_preset() const; void set_resolution_preset(const PlatformResolutionPreset& value_arg); @@ -101,9 +105,9 @@ class PlatformMediaSettings { bool enable_audio() const; void set_enable_audio(bool value_arg); + private: - static PlatformMediaSettings FromEncodableList( - const flutter::EncodableList& list); + static PlatformMediaSettings FromEncodableList(const flutter::EncodableList& list); flutter::EncodableList ToEncodableList() const; friend class CameraApi; friend class PigeonCodecSerializer; @@ -112,15 +116,19 @@ class PlatformMediaSettings { std::optional video_bitrate_; std::optional audio_bitrate_; bool enable_audio_; + }; + // A representation of a size from the native camera APIs. // // Generated class from Pigeon that represents data sent in messages. class PlatformSize { public: // Constructs an object setting all fields. - explicit PlatformSize(double width, double height); + explicit PlatformSize( + double width, + double height); double width() const; void set_width(double value_arg); @@ -128,6 +136,7 @@ class PlatformSize { double height() const; void set_height(double value_arg); + private: static PlatformSize FromEncodableList(const flutter::EncodableList& list); flutter::EncodableList ToEncodableList() const; @@ -135,8 +144,10 @@ class PlatformSize { friend class PigeonCodecSerializer; double width_; double height_; + }; + // Pigeon version of the relevant subset of VideoCaptureOptions. // // Generated class from Pigeon that represents data sent in messages. @@ -146,20 +157,20 @@ class PlatformVideoCaptureOptions { PlatformVideoCaptureOptions(); // Constructs an object setting all fields. - explicit PlatformVideoCaptureOptions( - const int64_t* max_duration_milliseconds); + explicit PlatformVideoCaptureOptions(const int64_t* max_duration_milliseconds); const int64_t* max_duration_milliseconds() const; void set_max_duration_milliseconds(const int64_t* value_arg); void set_max_duration_milliseconds(int64_t value_arg); + private: - static PlatformVideoCaptureOptions FromEncodableList( - const flutter::EncodableList& list); + static PlatformVideoCaptureOptions FromEncodableList(const flutter::EncodableList& list); flutter::EncodableList ToEncodableList() const; friend class CameraApi; friend class PigeonCodecSerializer; std::optional max_duration_milliseconds_; + }; class PigeonCodecSerializer : public flutter::StandardCodecSerializer { @@ -170,16 +181,18 @@ class PigeonCodecSerializer : public flutter::StandardCodecSerializer { return sInstance; } - void WriteValue(const flutter::EncodableValue& value, - flutter::ByteStreamWriter* stream) const override; + void WriteValue( + const flutter::EncodableValue& value, + flutter::ByteStreamWriter* stream) const override; protected: flutter::EncodableValue ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const override; + uint8_t type, + flutter::ByteStreamReader* stream) const override; + }; -// Generated interface from Pigeon that represents a handler of messages from -// Flutter. +// Generated interface from Pigeon that represents a handler of messages from Flutter. class CameraApi { public: CameraApi(const CameraApi&) = delete; @@ -188,50 +201,64 @@ class CameraApi { // Returns the names of all of the available capture devices. virtual ErrorOr GetAvailableCameras() = 0; // Creates a camera instance for the given device name and settings. - virtual void Create(const std::string& camera_name, - const PlatformMediaSettings& settings, - std::function reply)> result) = 0; + virtual void Create( + const std::string& camera_name, + const PlatformMediaSettings& settings, + std::function reply)> result) = 0; // Initializes a camera, and returns the size of its preview. virtual void Initialize( - int64_t camera_id, - std::function reply)> result) = 0; + int64_t camera_id, + std::function reply)> result) = 0; // Disposes a camera that is no longer in use. virtual std::optional Dispose(int64_t camera_id) = 0; // Takes a picture with the given camera, and returns the path to the // resulting file. virtual void TakePicture( - int64_t camera_id, - std::function reply)> result) = 0; + int64_t camera_id, + std::function reply)> result) = 0; // Starts recording video with the given camera. virtual void StartVideoRecording( - int64_t camera_id, const PlatformVideoCaptureOptions& options, - std::function reply)> result) = 0; + int64_t camera_id, + const PlatformVideoCaptureOptions& options, + std::function reply)> result) = 0; // Finishes recording video with the given camera, and returns the path to // the resulting file. virtual void StopVideoRecording( - int64_t camera_id, - std::function reply)> result) = 0; + int64_t camera_id, + std::function reply)> result) = 0; + // Starts the image stream for the given camera. + virtual void StartImageStream( + int64_t camera_id, + std::function reply)> result) = 0; + // Stops the image stream for the given camera. + virtual void StopImageStream( + int64_t camera_id, + std::function reply)> result) = 0; // Starts the preview stream for the given camera. virtual void PausePreview( - int64_t camera_id, - std::function reply)> result) = 0; + int64_t camera_id, + std::function reply)> result) = 0; // Resumes the preview stream for the given camera. virtual void ResumePreview( - int64_t camera_id, - std::function reply)> result) = 0; + int64_t camera_id, + std::function reply)> result) = 0; // The codec used by CameraApi. static const flutter::StandardMessageCodec& GetCodec(); - // Sets up an instance of `CameraApi` to handle messages through the - // `binary_messenger`. - static void SetUp(flutter::BinaryMessenger* binary_messenger, CameraApi* api); - static void SetUp(flutter::BinaryMessenger* binary_messenger, CameraApi* api, - const std::string& message_channel_suffix); + // Sets up an instance of `CameraApi` to handle messages through the `binary_messenger`. + static void SetUp( + flutter::BinaryMessenger* binary_messenger, + CameraApi* api); + static void SetUp( + flutter::BinaryMessenger* binary_messenger, + CameraApi* api, + const std::string& message_channel_suffix); static flutter::EncodableValue WrapError(std::string_view error_message); static flutter::EncodableValue WrapError(const FlutterError& error); protected: CameraApi() = default; + }; } // namespace camera_windows #endif // PIGEON_MESSAGES_G_H_ From b725973561404efc3af169f650b700af7251648b Mon Sep 17 00:00:00 2001 From: Jacob Lund Date: Thu, 11 Jul 2024 10:56:27 +0930 Subject: [PATCH 06/16] accepted the wrong changes --- .../camera_windows/windows/messages.g.cpp | 740 ++++++++---------- .../camera_windows/windows/messages.g.h | 27 - 2 files changed, 331 insertions(+), 436 deletions(-) diff --git a/packages/camera/camera_windows/windows/messages.g.cpp b/packages/camera/camera_windows/windows/messages.g.cpp index c2824f5fab7e..01bd140708ce 100644 --- a/packages/camera/camera_windows/windows/messages.g.cpp +++ b/packages/camera/camera_windows/windows/messages.g.cpp @@ -25,106 +25,104 @@ using flutter::EncodableMap; using flutter::EncodableValue; FlutterError CreateConnectionError(const std::string channel_name) { - return FlutterError( - "channel-error", - "Unable to establish connection on channel: '" + channel_name + "'.", - EncodableValue("")); + return FlutterError( + "channel-error", + "Unable to establish connection on channel: '" + channel_name + "'.", + EncodableValue("")); } // PlatformMediaSettings PlatformMediaSettings::PlatformMediaSettings( - const PlatformResolutionPreset& resolution_preset, bool enable_audio) - : resolution_preset_(resolution_preset), enable_audio_(enable_audio) {} + const PlatformResolutionPreset& resolution_preset, + bool enable_audio) + : resolution_preset_(resolution_preset), + enable_audio_(enable_audio) {} PlatformMediaSettings::PlatformMediaSettings( - const PlatformResolutionPreset& resolution_preset, - const int64_t* frames_per_second, const int64_t* video_bitrate, - const int64_t* audio_bitrate, bool enable_audio) - : resolution_preset_(resolution_preset), - frames_per_second_(frames_per_second - ? std::optional(*frames_per_second) - : std::nullopt), - video_bitrate_(video_bitrate ? std::optional(*video_bitrate) - : std::nullopt), - audio_bitrate_(audio_bitrate ? std::optional(*audio_bitrate) - : std::nullopt), - enable_audio_(enable_audio) {} - -const PlatformResolutionPreset& PlatformMediaSettings::resolution_preset() - const { + const PlatformResolutionPreset& resolution_preset, + const int64_t* frames_per_second, + const int64_t* video_bitrate, + const int64_t* audio_bitrate, + bool enable_audio) + : resolution_preset_(resolution_preset), + frames_per_second_(frames_per_second ? std::optional(*frames_per_second) : std::nullopt), + video_bitrate_(video_bitrate ? std::optional(*video_bitrate) : std::nullopt), + audio_bitrate_(audio_bitrate ? std::optional(*audio_bitrate) : std::nullopt), + enable_audio_(enable_audio) {} + +const PlatformResolutionPreset& PlatformMediaSettings::resolution_preset() const { return resolution_preset_; } -void PlatformMediaSettings::set_resolution_preset( - const PlatformResolutionPreset& value_arg) { +void PlatformMediaSettings::set_resolution_preset(const PlatformResolutionPreset& value_arg) { resolution_preset_ = value_arg; } + const int64_t* PlatformMediaSettings::frames_per_second() const { return frames_per_second_ ? &(*frames_per_second_) : nullptr; } void PlatformMediaSettings::set_frames_per_second(const int64_t* value_arg) { - frames_per_second_ = - value_arg ? std::optional(*value_arg) : std::nullopt; + frames_per_second_ = value_arg ? std::optional(*value_arg) : std::nullopt; } void PlatformMediaSettings::set_frames_per_second(int64_t value_arg) { frames_per_second_ = value_arg; } + const int64_t* PlatformMediaSettings::video_bitrate() const { return video_bitrate_ ? &(*video_bitrate_) : nullptr; } void PlatformMediaSettings::set_video_bitrate(const int64_t* value_arg) { - video_bitrate_ = - value_arg ? std::optional(*value_arg) : std::nullopt; + video_bitrate_ = value_arg ? std::optional(*value_arg) : std::nullopt; } void PlatformMediaSettings::set_video_bitrate(int64_t value_arg) { video_bitrate_ = value_arg; } + const int64_t* PlatformMediaSettings::audio_bitrate() const { return audio_bitrate_ ? &(*audio_bitrate_) : nullptr; } void PlatformMediaSettings::set_audio_bitrate(const int64_t* value_arg) { - audio_bitrate_ = - value_arg ? std::optional(*value_arg) : std::nullopt; + audio_bitrate_ = value_arg ? std::optional(*value_arg) : std::nullopt; } void PlatformMediaSettings::set_audio_bitrate(int64_t value_arg) { audio_bitrate_ = value_arg; } -bool PlatformMediaSettings::enable_audio() const { return enable_audio_; } + +bool PlatformMediaSettings::enable_audio() const { + return enable_audio_; +} void PlatformMediaSettings::set_enable_audio(bool value_arg) { enable_audio_ = value_arg; } + EncodableList PlatformMediaSettings::ToEncodableList() const { EncodableList list; list.reserve(5); list.push_back(CustomEncodableValue(resolution_preset_)); - list.push_back(frames_per_second_ ? EncodableValue(*frames_per_second_) - : EncodableValue()); - list.push_back(video_bitrate_ ? EncodableValue(*video_bitrate_) - : EncodableValue()); - list.push_back(audio_bitrate_ ? EncodableValue(*audio_bitrate_) - : EncodableValue()); + list.push_back(frames_per_second_ ? EncodableValue(*frames_per_second_) : EncodableValue()); + list.push_back(video_bitrate_ ? EncodableValue(*video_bitrate_) : EncodableValue()); + list.push_back(audio_bitrate_ ? EncodableValue(*audio_bitrate_) : EncodableValue()); list.push_back(EncodableValue(enable_audio_)); return list; } -PlatformMediaSettings PlatformMediaSettings::FromEncodableList( - const EncodableList& list) { - PlatformMediaSettings decoded(std::any_cast( - std::get(list[0])), - std::get(list[4])); +PlatformMediaSettings PlatformMediaSettings::FromEncodableList(const EncodableList& list) { + PlatformMediaSettings decoded( + std::any_cast(std::get(list[0])), + std::get(list[4])); auto& encodable_frames_per_second = list[1]; if (!encodable_frames_per_second.IsNull()) { decoded.set_frames_per_second(encodable_frames_per_second.LongValue()); @@ -142,16 +140,29 @@ PlatformMediaSettings PlatformMediaSettings::FromEncodableList( // PlatformSize -PlatformSize::PlatformSize(double width, double height) - : width_(width), height_(height) {} +PlatformSize::PlatformSize( + double width, + double height) + : width_(width), + height_(height) {} + +double PlatformSize::width() const { + return width_; +} + +void PlatformSize::set_width(double value_arg) { + width_ = value_arg; +} -double PlatformSize::width() const { return width_; } -void PlatformSize::set_width(double value_arg) { width_ = value_arg; } +double PlatformSize::height() const { + return height_; +} -double PlatformSize::height() const { return height_; } +void PlatformSize::set_height(double value_arg) { + height_ = value_arg; +} -void PlatformSize::set_height(double value_arg) { height_ = value_arg; } EncodableList PlatformSize::ToEncodableList() const { EncodableList list; @@ -162,60 +173,51 @@ EncodableList PlatformSize::ToEncodableList() const { } PlatformSize PlatformSize::FromEncodableList(const EncodableList& list) { - PlatformSize decoded(std::get(list[0]), std::get(list[1])); + PlatformSize decoded( + std::get(list[0]), + std::get(list[1])); return decoded; } + PigeonCodecSerializer::PigeonCodecSerializer() {} EncodableValue PigeonCodecSerializer::ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const { + uint8_t type, + flutter::ByteStreamReader* stream) const { switch (type) { case 129: - return CustomEncodableValue(PlatformMediaSettings::FromEncodableList( - std::get(ReadValue(stream)))); + return CustomEncodableValue(PlatformMediaSettings::FromEncodableList(std::get(ReadValue(stream)))); case 130: - return CustomEncodableValue(PlatformSize::FromEncodableList( - std::get(ReadValue(stream)))); - case 131: { - const auto& encodable_enum_arg = ReadValue(stream); - const int64_t enum_arg_value = - encodable_enum_arg.IsNull() ? 0 : encodable_enum_arg.LongValue(); - return encodable_enum_arg.IsNull() - ? EncodableValue() - : CustomEncodableValue( - static_cast(enum_arg_value)); - } + return CustomEncodableValue(PlatformSize::FromEncodableList(std::get(ReadValue(stream)))); + case 131: + { + const auto& encodable_enum_arg = ReadValue(stream); + const int64_t enum_arg_value = encodable_enum_arg.IsNull() ? 0 : encodable_enum_arg.LongValue(); + return encodable_enum_arg.IsNull() ? EncodableValue() : CustomEncodableValue(static_cast(enum_arg_value)); + } default: return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); - } + } } void PigeonCodecSerializer::WriteValue( - const EncodableValue& value, flutter::ByteStreamWriter* stream) const { - if (const CustomEncodableValue* custom_value = - std::get_if(&value)) { + const EncodableValue& value, + flutter::ByteStreamWriter* stream) const { + if (const CustomEncodableValue* custom_value = std::get_if(&value)) { if (custom_value->type() == typeid(PlatformMediaSettings)) { stream->WriteByte(129); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); + WriteValue(EncodableValue(std::any_cast(*custom_value).ToEncodableList()), stream); return; } if (custom_value->type() == typeid(PlatformSize)) { stream->WriteByte(130); - WriteValue( - EncodableValue( - std::any_cast(*custom_value).ToEncodableList()), - stream); + WriteValue(EncodableValue(std::any_cast(*custom_value).ToEncodableList()), stream); return; } if (custom_value->type() == typeid(PlatformResolutionPreset)) { stream->WriteByte(131); - WriteValue(EncodableValue(static_cast( - std::any_cast(*custom_value))), - stream); + WriteValue(EncodableValue(static_cast(std::any_cast(*custom_value))), stream); return; } } @@ -224,417 +226,333 @@ void PigeonCodecSerializer::WriteValue( /// The codec used by CameraApi. const flutter::StandardMessageCodec& CameraApi::GetCodec() { - return flutter::StandardMessageCodec::GetInstance( - &PigeonCodecSerializer::GetInstance()); + return flutter::StandardMessageCodec::GetInstance(&PigeonCodecSerializer::GetInstance()); } -// Sets up an instance of `CameraApi` to handle messages through the -// `binary_messenger`. -void CameraApi::SetUp(flutter::BinaryMessenger* binary_messenger, - CameraApi* api) { +// Sets up an instance of `CameraApi` to handle messages through the `binary_messenger`. +void CameraApi::SetUp( + flutter::BinaryMessenger* binary_messenger, + CameraApi* api) { CameraApi::SetUp(binary_messenger, api, ""); } -void CameraApi::SetUp(flutter::BinaryMessenger* binary_messenger, - CameraApi* api, - const std::string& message_channel_suffix) { - const std::string prepended_suffix = - message_channel_suffix.length() > 0 - ? std::string(".") + message_channel_suffix - : ""; +void CameraApi::SetUp( + flutter::BinaryMessenger* binary_messenger, + CameraApi* api, + const std::string& message_channel_suffix) { + const std::string prepended_suffix = message_channel_suffix.length() > 0 ? std::string(".") + message_channel_suffix : ""; { - BasicMessageChannel<> channel( - binary_messenger, - "dev.flutter.pigeon.camera_windows.CameraApi.getAvailableCameras" + - prepended_suffix, - &GetCodec()); + BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.camera_windows.CameraApi.getAvailableCameras" + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler( - [api](const EncodableValue& message, - const flutter::MessageReply& reply) { - try { - ErrorOr output = api->GetAvailableCameras(); - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); + channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { + try { + ErrorOr output = api->GetAvailableCameras(); + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel( - binary_messenger, - "dev.flutter.pigeon.camera_windows.CameraApi.create" + prepended_suffix, - &GetCodec()); + BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.camera_windows.CameraApi.create" + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler( - [api](const EncodableValue& message, - const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_camera_name_arg = args.at(0); - if (encodable_camera_name_arg.IsNull()) { - reply(WrapError("camera_name_arg unexpectedly null.")); - return; - } - const auto& camera_name_arg = - std::get(encodable_camera_name_arg); - const auto& encodable_settings_arg = args.at(1); - if (encodable_settings_arg.IsNull()) { - reply(WrapError("settings_arg unexpectedly null.")); - return; - } - const auto& settings_arg = - std::any_cast( - std::get(encodable_settings_arg)); - api->Create(camera_name_arg, settings_arg, - [reply](ErrorOr&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back( - EncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); + channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_camera_name_arg = args.at(0); + if (encodable_camera_name_arg.IsNull()) { + reply(WrapError("camera_name_arg unexpectedly null.")); + return; + } + const auto& camera_name_arg = std::get(encodable_camera_name_arg); + const auto& encodable_settings_arg = args.at(1); + if (encodable_settings_arg.IsNull()) { + reply(WrapError("settings_arg unexpectedly null.")); + return; + } + const auto& settings_arg = std::any_cast(std::get(encodable_settings_arg)); + api->Create(camera_name_arg, settings_arg, [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; } + EncodableList wrapped; + wrapped.push_back(EncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel( - binary_messenger, - "dev.flutter.pigeon.camera_windows.CameraApi.initialize" + - prepended_suffix, - &GetCodec()); + BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.camera_windows.CameraApi.initialize" + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler( - [api](const EncodableValue& message, - const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_camera_id_arg = args.at(0); - if (encodable_camera_id_arg.IsNull()) { - reply(WrapError("camera_id_arg unexpectedly null.")); - return; - } - const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); - api->Initialize( - camera_id_arg, [reply](ErrorOr&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back( - CustomEncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); + channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_camera_id_arg = args.at(0); + if (encodable_camera_id_arg.IsNull()) { + reply(WrapError("camera_id_arg unexpectedly null.")); + return; + } + const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); + api->Initialize(camera_id_arg, [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; } + EncodableList wrapped; + wrapped.push_back(CustomEncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel( - binary_messenger, - "dev.flutter.pigeon.camera_windows.CameraApi.dispose" + - prepended_suffix, - &GetCodec()); + BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.camera_windows.CameraApi.dispose" + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler( - [api](const EncodableValue& message, - const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_camera_id_arg = args.at(0); - if (encodable_camera_id_arg.IsNull()) { - reply(WrapError("camera_id_arg unexpectedly null.")); - return; - } - const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); - std::optional output = api->Dispose(camera_id_arg); - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); + channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_camera_id_arg = args.at(0); + if (encodable_camera_id_arg.IsNull()) { + reply(WrapError("camera_id_arg unexpectedly null.")); + return; + } + const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); + std::optional output = api->Dispose(camera_id_arg); + if (output.has_value()) { + reply(WrapError(output.value())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel( - binary_messenger, - "dev.flutter.pigeon.camera_windows.CameraApi.takePicture" + - prepended_suffix, - &GetCodec()); + BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.camera_windows.CameraApi.takePicture" + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler( - [api](const EncodableValue& message, - const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_camera_id_arg = args.at(0); - if (encodable_camera_id_arg.IsNull()) { - reply(WrapError("camera_id_arg unexpectedly null.")); - return; - } - const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); - api->TakePicture( - camera_id_arg, [reply](ErrorOr&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back( - EncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); + channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_camera_id_arg = args.at(0); + if (encodable_camera_id_arg.IsNull()) { + reply(WrapError("camera_id_arg unexpectedly null.")); + return; + } + const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); + api->TakePicture(camera_id_arg, [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; } + EncodableList wrapped; + wrapped.push_back(EncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel( - binary_messenger, - "dev.flutter.pigeon.camera_windows.CameraApi.startVideoRecording" + - prepended_suffix, - &GetCodec()); + BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.camera_windows.CameraApi.startVideoRecording" + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler( - [api](const EncodableValue& message, - const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_camera_id_arg = args.at(0); - if (encodable_camera_id_arg.IsNull()) { - reply(WrapError("camera_id_arg unexpectedly null.")); - return; - } - const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); - api->StartVideoRecording( - camera_id_arg, [reply](std::optional&& output) { - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); + channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_camera_id_arg = args.at(0); + if (encodable_camera_id_arg.IsNull()) { + reply(WrapError("camera_id_arg unexpectedly null.")); + return; + } + const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); + api->StartVideoRecording(camera_id_arg, [reply](std::optional&& output) { + if (output.has_value()) { + reply(WrapError(output.value())); + return; } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel( - binary_messenger, - "dev.flutter.pigeon.camera_windows.CameraApi.stopVideoRecording" + - prepended_suffix, - &GetCodec()); + BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.camera_windows.CameraApi.stopVideoRecording" + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler( - [api](const EncodableValue& message, - const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_camera_id_arg = args.at(0); - if (encodable_camera_id_arg.IsNull()) { - reply(WrapError("camera_id_arg unexpectedly null.")); - return; - } - const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); - api->StopVideoRecording( - camera_id_arg, [reply](ErrorOr&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back( - EncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); + channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_camera_id_arg = args.at(0); + if (encodable_camera_id_arg.IsNull()) { + reply(WrapError("camera_id_arg unexpectedly null.")); + return; + } + const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); + api->StopVideoRecording(camera_id_arg, [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; } + EncodableList wrapped; + wrapped.push_back(EncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel( - binary_messenger, - "dev.flutter.pigeon.camera_windows.CameraApi.startImageStream" + - prepended_suffix, - &GetCodec()); + BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.camera_windows.CameraApi.startImageStream" + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler( - [api](const EncodableValue& message, - const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_camera_id_arg = args.at(0); - if (encodable_camera_id_arg.IsNull()) { - reply(WrapError("camera_id_arg unexpectedly null.")); - return; - } - const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); - api->StartImageStream( - camera_id_arg, [reply](std::optional&& output) { - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); + channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_camera_id_arg = args.at(0); + if (encodable_camera_id_arg.IsNull()) { + reply(WrapError("camera_id_arg unexpectedly null.")); + return; + } + const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); + api->StartImageStream(camera_id_arg, [reply](std::optional&& output) { + if (output.has_value()) { + reply(WrapError(output.value())); + return; } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel( - binary_messenger, - "dev.flutter.pigeon.camera_windows.CameraApi.stopImageStream" + - prepended_suffix, - &GetCodec()); + BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.camera_windows.CameraApi.stopImageStream" + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler( - [api](const EncodableValue& message, - const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_camera_id_arg = args.at(0); - if (encodable_camera_id_arg.IsNull()) { - reply(WrapError("camera_id_arg unexpectedly null.")); - return; - } - const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); - api->StopImageStream( - camera_id_arg, [reply](std::optional&& output) { - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); + channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_camera_id_arg = args.at(0); + if (encodable_camera_id_arg.IsNull()) { + reply(WrapError("camera_id_arg unexpectedly null.")); + return; + } + const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); + api->StopImageStream(camera_id_arg, [reply](std::optional&& output) { + if (output.has_value()) { + reply(WrapError(output.value())); + return; } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel( - binary_messenger, - "dev.flutter.pigeon.camera_windows.CameraApi.pausePreview" + - prepended_suffix, - &GetCodec()); + BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.camera_windows.CameraApi.pausePreview" + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler( - [api](const EncodableValue& message, - const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_camera_id_arg = args.at(0); - if (encodable_camera_id_arg.IsNull()) { - reply(WrapError("camera_id_arg unexpectedly null.")); - return; - } - const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); - api->PausePreview(camera_id_arg, - [reply](std::optional&& output) { - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); + channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_camera_id_arg = args.at(0); + if (encodable_camera_id_arg.IsNull()) { + reply(WrapError("camera_id_arg unexpectedly null.")); + return; + } + const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); + api->PausePreview(camera_id_arg, [reply](std::optional&& output) { + if (output.has_value()) { + reply(WrapError(output.value())); + return; } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel( - binary_messenger, - "dev.flutter.pigeon.camera_windows.CameraApi.resumePreview" + - prepended_suffix, - &GetCodec()); + BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.camera_windows.CameraApi.resumePreview" + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler( - [api](const EncodableValue& message, - const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_camera_id_arg = args.at(0); - if (encodable_camera_id_arg.IsNull()) { - reply(WrapError("camera_id_arg unexpectedly null.")); - return; - } - const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); - api->ResumePreview(camera_id_arg, - [reply](std::optional&& output) { - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); + channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_camera_id_arg = args.at(0); + if (encodable_camera_id_arg.IsNull()) { + reply(WrapError("camera_id_arg unexpectedly null.")); + return; + } + const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); + api->ResumePreview(camera_id_arg, [reply](std::optional&& output) { + if (output.has_value()) { + reply(WrapError(output.value())); + return; } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); } else { channel.SetMessageHandler(nullptr); } @@ -642,15 +560,19 @@ void CameraApi::SetUp(flutter::BinaryMessenger* binary_messenger, } EncodableValue CameraApi::WrapError(std::string_view error_message) { - return EncodableValue( - EncodableList{EncodableValue(std::string(error_message)), - EncodableValue("Error"), EncodableValue()}); + return EncodableValue(EncodableList{ + EncodableValue(std::string(error_message)), + EncodableValue("Error"), + EncodableValue() + }); } EncodableValue CameraApi::WrapError(const FlutterError& error) { - return EncodableValue(EncodableList{EncodableValue(error.code()), - EncodableValue(error.message()), - error.details()}); + return EncodableValue(EncodableList{ + EncodableValue(error.code()), + EncodableValue(error.message()), + error.details() + }); } } // namespace camera_windows diff --git a/packages/camera/camera_windows/windows/messages.g.h b/packages/camera/camera_windows/windows/messages.g.h index 772aa3c6200d..81ddae51edde 100644 --- a/packages/camera/camera_windows/windows/messages.g.h +++ b/packages/camera/camera_windows/windows/messages.g.h @@ -147,32 +147,6 @@ class PlatformSize { }; - -// Pigeon version of the relevant subset of VideoCaptureOptions. -// -// Generated class from Pigeon that represents data sent in messages. -class PlatformVideoCaptureOptions { - public: - // Constructs an object setting all non-nullable fields. - PlatformVideoCaptureOptions(); - - // Constructs an object setting all fields. - explicit PlatformVideoCaptureOptions(const int64_t* max_duration_milliseconds); - - const int64_t* max_duration_milliseconds() const; - void set_max_duration_milliseconds(const int64_t* value_arg); - void set_max_duration_milliseconds(int64_t value_arg); - - - private: - static PlatformVideoCaptureOptions FromEncodableList(const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; - friend class CameraApi; - friend class PigeonCodecSerializer; - std::optional max_duration_milliseconds_; - -}; - class PigeonCodecSerializer : public flutter::StandardCodecSerializer { public: PigeonCodecSerializer(); @@ -219,7 +193,6 @@ class CameraApi { // Starts recording video with the given camera. virtual void StartVideoRecording( int64_t camera_id, - const PlatformVideoCaptureOptions& options, std::function reply)> result) = 0; // Finishes recording video with the given camera, and returns the path to // the resulting file. From dfa486cf6f8070590f4f3cc504338bb0c9ba8808 Mon Sep 17 00:00:00 2001 From: Jacob Lund Date: Wed, 24 Jul 2024 07:58:27 +0930 Subject: [PATCH 07/16] hopefully this is right --- packages/camera/camera_windows/CHANGELOG.md | 4 ++++ packages/camera/camera_windows/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/camera/camera_windows/CHANGELOG.md b/packages/camera/camera_windows/CHANGELOG.md index 47b54208fa80..df9a083b1a6d 100644 --- a/packages/camera/camera_windows/CHANGELOG.md +++ b/packages/camera/camera_windows/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.5 + +* Adds support for streaming frames. + ## 0.2.4+1 * Updates to pigeon 21. diff --git a/packages/camera/camera_windows/pubspec.yaml b/packages/camera/camera_windows/pubspec.yaml index 703c46bcb7db..2ed88b73714f 100644 --- a/packages/camera/camera_windows/pubspec.yaml +++ b/packages/camera/camera_windows/pubspec.yaml @@ -2,7 +2,7 @@ name: camera_windows description: A Flutter plugin for getting information about and controlling the camera on Windows. repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_windows issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.2.4+1 +version: 0.2.5 environment: sdk: ^3.2.0 From 76f0360159a2d38f3f9f2ad1426347780d1c9907 Mon Sep 17 00:00:00 2001 From: Jacob Lund Date: Wed, 24 Jul 2024 08:12:29 +0930 Subject: [PATCH 08/16] bump camera version --- packages/camera/camera/CHANGELOG.md | 4 ++++ packages/camera/camera/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md index 53a6c4ca1ad8..b9571baaddd8 100644 --- a/packages/camera/camera/CHANGELOG.md +++ b/packages/camera/camera/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.11.1 + +* Added support for image streaming to `camera_windows`. + ## 0.11.0+1 * Updates minimum supported SDK version to Flutter 3.16/Dart 3.2. diff --git a/packages/camera/camera/pubspec.yaml b/packages/camera/camera/pubspec.yaml index f00a7e798f01..6564581baeee 100644 --- a/packages/camera/camera/pubspec.yaml +++ b/packages/camera/camera/pubspec.yaml @@ -4,7 +4,7 @@ description: A Flutter plugin for controlling the camera. Supports previewing Dart. 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 -version: 0.11.0+1 +version: 0.11.1 environment: sdk: ^3.2.3 From 8a1dfc14defa4664c046f13e927e164c04914e41 Mon Sep 17 00:00:00 2001 From: Jacob Lund Date: Wed, 24 Jul 2024 08:14:31 +0930 Subject: [PATCH 09/16] formatting fixes --- .../windows/capture_controller.cpp | 30 +- .../windows/capture_controller.h | 10 +- .../camera_windows/windows/messages.g.cpp | 740 ++++++++++-------- .../camera_windows/windows/messages.g.h | 103 +-- .../camera_windows/windows/test/mocks.h | 7 +- 5 files changed, 479 insertions(+), 411 deletions(-) diff --git a/packages/camera/camera_windows/windows/capture_controller.cpp b/packages/camera/camera_windows/windows/capture_controller.cpp index c4cb3e85461c..f966eb52a41d 100644 --- a/packages/camera/camera_windows/windows/capture_controller.cpp +++ b/packages/camera/camera_windows/windows/capture_controller.cpp @@ -21,9 +21,6 @@ #include "string_utils.h" #include "texture_handler.h" - - - namespace camera_windows { using Microsoft::WRL::ComPtr; @@ -556,14 +553,15 @@ void CaptureControllerImpl::StopRecord() { "Failed to stop video recording"); } } -void CaptureControllerImpl::StartImageStream(std::unique_ptr> sink) { - assert(capture_controller_listener_); - image_stream_sink_ = std::move(sink); +void CaptureControllerImpl::StartImageStream( + std::unique_ptr> sink) { + assert(capture_controller_listener_); + image_stream_sink_ = std::move(sink); } void CaptureControllerImpl::StopImageStream() { - assert(capture_controller_listener_); - image_stream_sink_.reset(); + assert(capture_controller_listener_); + image_stream_sink_.reset(); } // Starts capturing preview frames using preview handler @@ -862,16 +860,21 @@ bool CaptureControllerImpl::UpdateBuffer(uint8_t* buffer, // Convert the buffer data to a std::vector. std::vector buffer_data(buffer, buffer + data_length); - // Ensure preview_frame_height_ and preview_frame_width_ are of supported types. + // Ensure preview_frame_height_ and preview_frame_width_ are of supported + // types. int preview_frame_height = static_cast(preview_frame_height_); int preview_frame_width = static_cast(preview_frame_width_); // Create a map to hold the buffer data and data length. flutter::EncodableMap data_map; - data_map[flutter::EncodableValue("data")] = flutter::EncodableValue(buffer_data); - data_map[flutter::EncodableValue("height")] = flutter::EncodableValue(preview_frame_height); - data_map[flutter::EncodableValue("width")] = flutter::EncodableValue(preview_frame_width); - data_map[flutter::EncodableValue("length")] = flutter::EncodableValue(static_cast(data_length)); + data_map[flutter::EncodableValue("data")] = + flutter::EncodableValue(buffer_data); + data_map[flutter::EncodableValue("height")] = + flutter::EncodableValue(preview_frame_height); + data_map[flutter::EncodableValue("width")] = + flutter::EncodableValue(preview_frame_width); + data_map[flutter::EncodableValue("length")] = + flutter::EncodableValue(static_cast(data_length)); // Wrap the map in a flutter::EncodableValue. flutter::EncodableValue encoded_value(data_map); @@ -880,7 +883,6 @@ bool CaptureControllerImpl::UpdateBuffer(uint8_t* buffer, image_stream_sink_->Success(encoded_value); } return texture_handler_->UpdateBuffer(buffer, data_length); - } // Handles capture time update from each processed frame. diff --git a/packages/camera/camera_windows/windows/capture_controller.h b/packages/camera/camera_windows/windows/capture_controller.h index a85f80b68446..20059dc765be 100644 --- a/packages/camera/camera_windows/windows/capture_controller.h +++ b/packages/camera/camera_windows/windows/capture_controller.h @@ -94,7 +94,8 @@ class CaptureController { virtual void StopRecord() = 0; // Starts image streaming. - virtual void StartImageStream(std::unique_ptr> sink) = 0; + virtual void StartImageStream( + std::unique_ptr> sink) = 0; // Stops the current image streaming. virtual void StopImageStream() = 0; @@ -132,7 +133,9 @@ class CaptureControllerImpl : public CaptureController, void ResumePreview() override; void StartRecord(const std::string& file_path) override; void StopRecord() override; - void StartImageStream(std::unique_ptr> sink) override; + void StartImageStream( + std::unique_ptr> sink) + override; void StopImageStream() override; void TakePicture(const std::string& file_path) override; @@ -224,7 +227,8 @@ class CaptureControllerImpl : public CaptureController, std::unique_ptr preview_handler_; std::unique_ptr photo_handler_; std::unique_ptr texture_handler_; - std::unique_ptr> image_stream_sink_; + std::unique_ptr> + image_stream_sink_; CaptureControllerListener* capture_controller_listener_; std::string video_device_id_; CaptureEngineState capture_engine_state_ = diff --git a/packages/camera/camera_windows/windows/messages.g.cpp b/packages/camera/camera_windows/windows/messages.g.cpp index 105b1fd9322c..08a91943f546 100644 --- a/packages/camera/camera_windows/windows/messages.g.cpp +++ b/packages/camera/camera_windows/windows/messages.g.cpp @@ -25,104 +25,106 @@ using flutter::EncodableMap; using flutter::EncodableValue; FlutterError CreateConnectionError(const std::string channel_name) { - return FlutterError( - "channel-error", - "Unable to establish connection on channel: '" + channel_name + "'.", - EncodableValue("")); + return FlutterError( + "channel-error", + "Unable to establish connection on channel: '" + channel_name + "'.", + EncodableValue("")); } // PlatformMediaSettings PlatformMediaSettings::PlatformMediaSettings( - const PlatformResolutionPreset& resolution_preset, - bool enable_audio) - : resolution_preset_(resolution_preset), - enable_audio_(enable_audio) {} + const PlatformResolutionPreset& resolution_preset, bool enable_audio) + : resolution_preset_(resolution_preset), enable_audio_(enable_audio) {} PlatformMediaSettings::PlatformMediaSettings( - const PlatformResolutionPreset& resolution_preset, - const int64_t* frames_per_second, - const int64_t* video_bitrate, - const int64_t* audio_bitrate, - bool enable_audio) - : resolution_preset_(resolution_preset), - frames_per_second_(frames_per_second ? std::optional(*frames_per_second) : std::nullopt), - video_bitrate_(video_bitrate ? std::optional(*video_bitrate) : std::nullopt), - audio_bitrate_(audio_bitrate ? std::optional(*audio_bitrate) : std::nullopt), - enable_audio_(enable_audio) {} - -const PlatformResolutionPreset& PlatformMediaSettings::resolution_preset() const { + const PlatformResolutionPreset& resolution_preset, + const int64_t* frames_per_second, const int64_t* video_bitrate, + const int64_t* audio_bitrate, bool enable_audio) + : resolution_preset_(resolution_preset), + frames_per_second_(frames_per_second + ? std::optional(*frames_per_second) + : std::nullopt), + video_bitrate_(video_bitrate ? std::optional(*video_bitrate) + : std::nullopt), + audio_bitrate_(audio_bitrate ? std::optional(*audio_bitrate) + : std::nullopt), + enable_audio_(enable_audio) {} + +const PlatformResolutionPreset& PlatformMediaSettings::resolution_preset() + const { return resolution_preset_; } -void PlatformMediaSettings::set_resolution_preset(const PlatformResolutionPreset& value_arg) { +void PlatformMediaSettings::set_resolution_preset( + const PlatformResolutionPreset& value_arg) { resolution_preset_ = value_arg; } - const int64_t* PlatformMediaSettings::frames_per_second() const { return frames_per_second_ ? &(*frames_per_second_) : nullptr; } void PlatformMediaSettings::set_frames_per_second(const int64_t* value_arg) { - frames_per_second_ = value_arg ? std::optional(*value_arg) : std::nullopt; + frames_per_second_ = + value_arg ? std::optional(*value_arg) : std::nullopt; } void PlatformMediaSettings::set_frames_per_second(int64_t value_arg) { frames_per_second_ = value_arg; } - const int64_t* PlatformMediaSettings::video_bitrate() const { return video_bitrate_ ? &(*video_bitrate_) : nullptr; } void PlatformMediaSettings::set_video_bitrate(const int64_t* value_arg) { - video_bitrate_ = value_arg ? std::optional(*value_arg) : std::nullopt; + video_bitrate_ = + value_arg ? std::optional(*value_arg) : std::nullopt; } void PlatformMediaSettings::set_video_bitrate(int64_t value_arg) { video_bitrate_ = value_arg; } - const int64_t* PlatformMediaSettings::audio_bitrate() const { return audio_bitrate_ ? &(*audio_bitrate_) : nullptr; } void PlatformMediaSettings::set_audio_bitrate(const int64_t* value_arg) { - audio_bitrate_ = value_arg ? std::optional(*value_arg) : std::nullopt; + audio_bitrate_ = + value_arg ? std::optional(*value_arg) : std::nullopt; } void PlatformMediaSettings::set_audio_bitrate(int64_t value_arg) { audio_bitrate_ = value_arg; } - -bool PlatformMediaSettings::enable_audio() const { - return enable_audio_; -} +bool PlatformMediaSettings::enable_audio() const { return enable_audio_; } void PlatformMediaSettings::set_enable_audio(bool value_arg) { enable_audio_ = value_arg; } - EncodableList PlatformMediaSettings::ToEncodableList() const { EncodableList list; list.reserve(5); list.push_back(CustomEncodableValue(resolution_preset_)); - list.push_back(frames_per_second_ ? EncodableValue(*frames_per_second_) : EncodableValue()); - list.push_back(video_bitrate_ ? EncodableValue(*video_bitrate_) : EncodableValue()); - list.push_back(audio_bitrate_ ? EncodableValue(*audio_bitrate_) : EncodableValue()); + list.push_back(frames_per_second_ ? EncodableValue(*frames_per_second_) + : EncodableValue()); + list.push_back(video_bitrate_ ? EncodableValue(*video_bitrate_) + : EncodableValue()); + list.push_back(audio_bitrate_ ? EncodableValue(*audio_bitrate_) + : EncodableValue()); list.push_back(EncodableValue(enable_audio_)); return list; } -PlatformMediaSettings PlatformMediaSettings::FromEncodableList(const EncodableList& list) { - PlatformMediaSettings decoded( - std::any_cast(std::get(list[0])), - std::get(list[4])); +PlatformMediaSettings PlatformMediaSettings::FromEncodableList( + const EncodableList& list) { + PlatformMediaSettings decoded(std::any_cast( + std::get(list[0])), + std::get(list[4])); auto& encodable_frames_per_second = list[1]; if (!encodable_frames_per_second.IsNull()) { decoded.set_frames_per_second(encodable_frames_per_second.LongValue()); @@ -140,29 +142,16 @@ PlatformMediaSettings PlatformMediaSettings::FromEncodableList(const EncodableLi // PlatformSize -PlatformSize::PlatformSize( - double width, - double height) - : width_(width), - height_(height) {} - -double PlatformSize::width() const { - return width_; -} - -void PlatformSize::set_width(double value_arg) { - width_ = value_arg; -} +PlatformSize::PlatformSize(double width, double height) + : width_(width), height_(height) {} +double PlatformSize::width() const { return width_; } -double PlatformSize::height() const { - return height_; -} +void PlatformSize::set_width(double value_arg) { width_ = value_arg; } -void PlatformSize::set_height(double value_arg) { - height_ = value_arg; -} +double PlatformSize::height() const { return height_; } +void PlatformSize::set_height(double value_arg) { height_ = value_arg; } EncodableList PlatformSize::ToEncodableList() const { EncodableList list; @@ -173,51 +162,60 @@ EncodableList PlatformSize::ToEncodableList() const { } PlatformSize PlatformSize::FromEncodableList(const EncodableList& list) { - PlatformSize decoded( - std::get(list[0]), - std::get(list[1])); + PlatformSize decoded(std::get(list[0]), std::get(list[1])); return decoded; } - PigeonCodecSerializer::PigeonCodecSerializer() {} EncodableValue PigeonCodecSerializer::ReadValueOfType( - uint8_t type, - flutter::ByteStreamReader* stream) const { + uint8_t type, flutter::ByteStreamReader* stream) const { switch (type) { case 129: - return CustomEncodableValue(PlatformMediaSettings::FromEncodableList(std::get(ReadValue(stream)))); + return CustomEncodableValue(PlatformMediaSettings::FromEncodableList( + std::get(ReadValue(stream)))); case 130: - return CustomEncodableValue(PlatformSize::FromEncodableList(std::get(ReadValue(stream)))); - case 131: - { - const auto& encodable_enum_arg = ReadValue(stream); - const int64_t enum_arg_value = encodable_enum_arg.IsNull() ? 0 : encodable_enum_arg.LongValue(); - return encodable_enum_arg.IsNull() ? EncodableValue() : CustomEncodableValue(static_cast(enum_arg_value)); - } + return CustomEncodableValue(PlatformSize::FromEncodableList( + std::get(ReadValue(stream)))); + case 131: { + const auto& encodable_enum_arg = ReadValue(stream); + const int64_t enum_arg_value = + encodable_enum_arg.IsNull() ? 0 : encodable_enum_arg.LongValue(); + return encodable_enum_arg.IsNull() + ? EncodableValue() + : CustomEncodableValue( + static_cast(enum_arg_value)); + } default: return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); - } + } } void PigeonCodecSerializer::WriteValue( - const EncodableValue& value, - flutter::ByteStreamWriter* stream) const { - if (const CustomEncodableValue* custom_value = std::get_if(&value)) { + const EncodableValue& value, flutter::ByteStreamWriter* stream) const { + if (const CustomEncodableValue* custom_value = + std::get_if(&value)) { if (custom_value->type() == typeid(PlatformMediaSettings)) { stream->WriteByte(129); - WriteValue(EncodableValue(std::any_cast(*custom_value).ToEncodableList()), stream); + WriteValue( + EncodableValue(std::any_cast(*custom_value) + .ToEncodableList()), + stream); return; } if (custom_value->type() == typeid(PlatformSize)) { stream->WriteByte(130); - WriteValue(EncodableValue(std::any_cast(*custom_value).ToEncodableList()), stream); + WriteValue( + EncodableValue( + std::any_cast(*custom_value).ToEncodableList()), + stream); return; } if (custom_value->type() == typeid(PlatformResolutionPreset)) { stream->WriteByte(131); - WriteValue(EncodableValue(static_cast(std::any_cast(*custom_value))), stream); + WriteValue(EncodableValue(static_cast( + std::any_cast(*custom_value))), + stream); return; } } @@ -226,333 +224,417 @@ void PigeonCodecSerializer::WriteValue( /// The codec used by CameraApi. const flutter::StandardMessageCodec& CameraApi::GetCodec() { - return flutter::StandardMessageCodec::GetInstance(&PigeonCodecSerializer::GetInstance()); + return flutter::StandardMessageCodec::GetInstance( + &PigeonCodecSerializer::GetInstance()); } -// Sets up an instance of `CameraApi` to handle messages through the `binary_messenger`. -void CameraApi::SetUp( - flutter::BinaryMessenger* binary_messenger, - CameraApi* api) { +// Sets up an instance of `CameraApi` to handle messages through the +// `binary_messenger`. +void CameraApi::SetUp(flutter::BinaryMessenger* binary_messenger, + CameraApi* api) { CameraApi::SetUp(binary_messenger, api, ""); } -void CameraApi::SetUp( - flutter::BinaryMessenger* binary_messenger, - CameraApi* api, - const std::string& message_channel_suffix) { - const std::string prepended_suffix = message_channel_suffix.length() > 0 ? std::string(".") + message_channel_suffix : ""; +void CameraApi::SetUp(flutter::BinaryMessenger* binary_messenger, + CameraApi* api, + const std::string& message_channel_suffix) { + const std::string prepended_suffix = + message_channel_suffix.length() > 0 + ? std::string(".") + message_channel_suffix + : ""; { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.camera_windows.CameraApi.getAvailableCameras" + prepended_suffix, &GetCodec()); + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.camera_windows.CameraApi.getAvailableCameras" + + prepended_suffix, + &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - ErrorOr output = api->GetAvailableCameras(); - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); + channel.SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + ErrorOr output = api->GetAvailableCameras(); + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.camera_windows.CameraApi.create" + prepended_suffix, &GetCodec()); + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.camera_windows.CameraApi.create" + prepended_suffix, + &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_camera_name_arg = args.at(0); - if (encodable_camera_name_arg.IsNull()) { - reply(WrapError("camera_name_arg unexpectedly null.")); - return; - } - const auto& camera_name_arg = std::get(encodable_camera_name_arg); - const auto& encodable_settings_arg = args.at(1); - if (encodable_settings_arg.IsNull()) { - reply(WrapError("settings_arg unexpectedly null.")); - return; - } - const auto& settings_arg = std::any_cast(std::get(encodable_settings_arg)); - api->Create(camera_name_arg, settings_arg, [reply](ErrorOr&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; + channel.SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_camera_name_arg = args.at(0); + if (encodable_camera_name_arg.IsNull()) { + reply(WrapError("camera_name_arg unexpectedly null.")); + return; + } + const auto& camera_name_arg = + std::get(encodable_camera_name_arg); + const auto& encodable_settings_arg = args.at(1); + if (encodable_settings_arg.IsNull()) { + reply(WrapError("settings_arg unexpectedly null.")); + return; + } + const auto& settings_arg = + std::any_cast( + std::get(encodable_settings_arg)); + api->Create(camera_name_arg, settings_arg, + [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back( + EncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); } - EncodableList wrapped; - wrapped.push_back(EncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.camera_windows.CameraApi.initialize" + prepended_suffix, &GetCodec()); + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.camera_windows.CameraApi.initialize" + + prepended_suffix, + &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_camera_id_arg = args.at(0); - if (encodable_camera_id_arg.IsNull()) { - reply(WrapError("camera_id_arg unexpectedly null.")); - return; - } - const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); - api->Initialize(camera_id_arg, [reply](ErrorOr&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; + channel.SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_camera_id_arg = args.at(0); + if (encodable_camera_id_arg.IsNull()) { + reply(WrapError("camera_id_arg unexpectedly null.")); + return; + } + const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); + api->Initialize( + camera_id_arg, [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back( + CustomEncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); } - EncodableList wrapped; - wrapped.push_back(CustomEncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.camera_windows.CameraApi.dispose" + prepended_suffix, &GetCodec()); + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.camera_windows.CameraApi.dispose" + + prepended_suffix, + &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_camera_id_arg = args.at(0); - if (encodable_camera_id_arg.IsNull()) { - reply(WrapError("camera_id_arg unexpectedly null.")); - return; - } - const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); - std::optional output = api->Dispose(camera_id_arg); - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); + channel.SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_camera_id_arg = args.at(0); + if (encodable_camera_id_arg.IsNull()) { + reply(WrapError("camera_id_arg unexpectedly null.")); + return; + } + const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); + std::optional output = api->Dispose(camera_id_arg); + if (output.has_value()) { + reply(WrapError(output.value())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.camera_windows.CameraApi.takePicture" + prepended_suffix, &GetCodec()); + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.camera_windows.CameraApi.takePicture" + + prepended_suffix, + &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_camera_id_arg = args.at(0); - if (encodable_camera_id_arg.IsNull()) { - reply(WrapError("camera_id_arg unexpectedly null.")); - return; - } - const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); - api->TakePicture(camera_id_arg, [reply](ErrorOr&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; + channel.SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_camera_id_arg = args.at(0); + if (encodable_camera_id_arg.IsNull()) { + reply(WrapError("camera_id_arg unexpectedly null.")); + return; + } + const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); + api->TakePicture( + camera_id_arg, [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back( + EncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); } - EncodableList wrapped; - wrapped.push_back(EncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.camera_windows.CameraApi.startVideoRecording" + prepended_suffix, &GetCodec()); + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.camera_windows.CameraApi.startVideoRecording" + + prepended_suffix, + &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_camera_id_arg = args.at(0); - if (encodable_camera_id_arg.IsNull()) { - reply(WrapError("camera_id_arg unexpectedly null.")); - return; - } - const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); - api->StartVideoRecording(camera_id_arg, [reply](std::optional&& output) { - if (output.has_value()) { - reply(WrapError(output.value())); - return; + channel.SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_camera_id_arg = args.at(0); + if (encodable_camera_id_arg.IsNull()) { + reply(WrapError("camera_id_arg unexpectedly null.")); + return; + } + const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); + api->StartVideoRecording( + camera_id_arg, [reply](std::optional&& output) { + if (output.has_value()) { + reply(WrapError(output.value())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.camera_windows.CameraApi.stopVideoRecording" + prepended_suffix, &GetCodec()); + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.camera_windows.CameraApi.stopVideoRecording" + + prepended_suffix, + &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_camera_id_arg = args.at(0); - if (encodable_camera_id_arg.IsNull()) { - reply(WrapError("camera_id_arg unexpectedly null.")); - return; - } - const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); - api->StopVideoRecording(camera_id_arg, [reply](ErrorOr&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; + channel.SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_camera_id_arg = args.at(0); + if (encodable_camera_id_arg.IsNull()) { + reply(WrapError("camera_id_arg unexpectedly null.")); + return; + } + const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); + api->StopVideoRecording( + camera_id_arg, [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back( + EncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); } - EncodableList wrapped; - wrapped.push_back(EncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.camera_windows.CameraApi.startImageStream" + prepended_suffix, &GetCodec()); + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.camera_windows.CameraApi.startImageStream" + + prepended_suffix, + &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_camera_id_arg = args.at(0); - if (encodable_camera_id_arg.IsNull()) { - reply(WrapError("camera_id_arg unexpectedly null.")); - return; - } - const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); - api->StartImageStream(camera_id_arg, [reply](std::optional&& output) { - if (output.has_value()) { - reply(WrapError(output.value())); - return; + channel.SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_camera_id_arg = args.at(0); + if (encodable_camera_id_arg.IsNull()) { + reply(WrapError("camera_id_arg unexpectedly null.")); + return; + } + const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); + api->StartImageStream( + camera_id_arg, [reply](std::optional&& output) { + if (output.has_value()) { + reply(WrapError(output.value())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.camera_windows.CameraApi.stopImageStream" + prepended_suffix, &GetCodec()); + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.camera_windows.CameraApi.stopImageStream" + + prepended_suffix, + &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_camera_id_arg = args.at(0); - if (encodable_camera_id_arg.IsNull()) { - reply(WrapError("camera_id_arg unexpectedly null.")); - return; - } - const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); - api->StopImageStream(camera_id_arg, [reply](std::optional&& output) { - if (output.has_value()) { - reply(WrapError(output.value())); - return; + channel.SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_camera_id_arg = args.at(0); + if (encodable_camera_id_arg.IsNull()) { + reply(WrapError("camera_id_arg unexpectedly null.")); + return; + } + const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); + api->StopImageStream( + camera_id_arg, [reply](std::optional&& output) { + if (output.has_value()) { + reply(WrapError(output.value())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.camera_windows.CameraApi.pausePreview" + prepended_suffix, &GetCodec()); + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.camera_windows.CameraApi.pausePreview" + + prepended_suffix, + &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_camera_id_arg = args.at(0); - if (encodable_camera_id_arg.IsNull()) { - reply(WrapError("camera_id_arg unexpectedly null.")); - return; - } - const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); - api->PausePreview(camera_id_arg, [reply](std::optional&& output) { - if (output.has_value()) { - reply(WrapError(output.value())); - return; + channel.SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_camera_id_arg = args.at(0); + if (encodable_camera_id_arg.IsNull()) { + reply(WrapError("camera_id_arg unexpectedly null.")); + return; + } + const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); + api->PausePreview(camera_id_arg, + [reply](std::optional&& output) { + if (output.has_value()) { + reply(WrapError(output.value())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); } else { channel.SetMessageHandler(nullptr); } } { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.camera_windows.CameraApi.resumePreview" + prepended_suffix, &GetCodec()); + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.camera_windows.CameraApi.resumePreview" + + prepended_suffix, + &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_camera_id_arg = args.at(0); - if (encodable_camera_id_arg.IsNull()) { - reply(WrapError("camera_id_arg unexpectedly null.")); - return; - } - const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); - api->ResumePreview(camera_id_arg, [reply](std::optional&& output) { - if (output.has_value()) { - reply(WrapError(output.value())); - return; + channel.SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_camera_id_arg = args.at(0); + if (encodable_camera_id_arg.IsNull()) { + reply(WrapError("camera_id_arg unexpectedly null.")); + return; + } + const int64_t camera_id_arg = encodable_camera_id_arg.LongValue(); + api->ResumePreview(camera_id_arg, + [reply](std::optional&& output) { + if (output.has_value()) { + reply(WrapError(output.value())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); } else { channel.SetMessageHandler(nullptr); } @@ -560,19 +642,15 @@ void CameraApi::SetUp( } EncodableValue CameraApi::WrapError(std::string_view error_message) { - return EncodableValue(EncodableList{ - EncodableValue(std::string(error_message)), - EncodableValue("Error"), - EncodableValue() - }); + return EncodableValue( + EncodableList{EncodableValue(std::string(error_message)), + EncodableValue("Error"), EncodableValue()}); } EncodableValue CameraApi::WrapError(const FlutterError& error) { - return EncodableValue(EncodableList{ - EncodableValue(error.code()), - EncodableValue(error.message()), - error.details() - }); + return EncodableValue(EncodableList{EncodableValue(error.code()), + EncodableValue(error.message()), + error.details()}); } } // namespace camera_windows diff --git a/packages/camera/camera_windows/windows/messages.g.h b/packages/camera/camera_windows/windows/messages.g.h index 9e2e11e301f0..e4e42ce9e50b 100644 --- a/packages/camera/camera_windows/windows/messages.g.h +++ b/packages/camera/camera_windows/windows/messages.g.h @@ -17,17 +17,16 @@ namespace camera_windows { - // Generated class from Pigeon. class FlutterError { public: - explicit FlutterError(const std::string& code) - : code_(code) {} + explicit FlutterError(const std::string& code) : code_(code) {} explicit FlutterError(const std::string& code, const std::string& message) - : code_(code), message_(message) {} - explicit FlutterError(const std::string& code, const std::string& message, const flutter::EncodableValue& details) - : code_(code), message_(message), details_(details) {} + : code_(code), message_(message) {} + explicit FlutterError(const std::string& code, const std::string& message, + const flutter::EncodableValue& details) + : code_(code), message_(message), details_(details) {} const std::string& code() const { return code_; } const std::string& message() const { return message_; } @@ -39,7 +38,8 @@ class FlutterError { flutter::EncodableValue details_; }; -template class ErrorOr { +template +class ErrorOr { public: ErrorOr(const T& rhs) : v_(rhs) {} ErrorOr(const T&& rhs) : v_(std::move(rhs)) {} @@ -58,7 +58,6 @@ template class ErrorOr { std::variant v_; }; - // Pigeon version of platform interface's ResolutionPreset. enum class PlatformResolutionPreset { kLow = 0, @@ -76,16 +75,13 @@ class PlatformMediaSettings { public: // Constructs an object setting all non-nullable fields. explicit PlatformMediaSettings( - const PlatformResolutionPreset& resolution_preset, - bool enable_audio); + const PlatformResolutionPreset& resolution_preset, bool enable_audio); // Constructs an object setting all fields. explicit PlatformMediaSettings( - const PlatformResolutionPreset& resolution_preset, - const int64_t* frames_per_second, - const int64_t* video_bitrate, - const int64_t* audio_bitrate, - bool enable_audio); + const PlatformResolutionPreset& resolution_preset, + const int64_t* frames_per_second, const int64_t* video_bitrate, + const int64_t* audio_bitrate, bool enable_audio); const PlatformResolutionPreset& resolution_preset() const; void set_resolution_preset(const PlatformResolutionPreset& value_arg); @@ -105,9 +101,9 @@ class PlatformMediaSettings { bool enable_audio() const; void set_enable_audio(bool value_arg); - private: - static PlatformMediaSettings FromEncodableList(const flutter::EncodableList& list); + static PlatformMediaSettings FromEncodableList( + const flutter::EncodableList& list); flutter::EncodableList ToEncodableList() const; friend class CameraApi; friend class PigeonCodecSerializer; @@ -116,19 +112,15 @@ class PlatformMediaSettings { std::optional video_bitrate_; std::optional audio_bitrate_; bool enable_audio_; - }; - // A representation of a size from the native camera APIs. // // Generated class from Pigeon that represents data sent in messages. class PlatformSize { public: // Constructs an object setting all fields. - explicit PlatformSize( - double width, - double height); + explicit PlatformSize(double width, double height); double width() const; void set_width(double value_arg); @@ -136,7 +128,6 @@ class PlatformSize { double height() const; void set_height(double value_arg); - private: static PlatformSize FromEncodableList(const flutter::EncodableList& list); flutter::EncodableList ToEncodableList() const; @@ -144,7 +135,6 @@ class PlatformSize { friend class PigeonCodecSerializer; double width_; double height_; - }; class PigeonCodecSerializer : public flutter::StandardCodecSerializer { @@ -155,18 +145,16 @@ class PigeonCodecSerializer : public flutter::StandardCodecSerializer { return sInstance; } - void WriteValue( - const flutter::EncodableValue& value, - flutter::ByteStreamWriter* stream) const override; + void WriteValue(const flutter::EncodableValue& value, + flutter::ByteStreamWriter* stream) const override; protected: flutter::EncodableValue ReadValueOfType( - uint8_t type, - flutter::ByteStreamReader* stream) const override; - + uint8_t type, flutter::ByteStreamReader* stream) const override; }; -// Generated interface from Pigeon that represents a handler of messages from Flutter. +// Generated interface from Pigeon that represents a handler of messages from +// Flutter. class CameraApi { public: CameraApi(const CameraApi&) = delete; @@ -175,63 +163,58 @@ class CameraApi { // Returns the names of all of the available capture devices. virtual ErrorOr GetAvailableCameras() = 0; // Creates a camera instance for the given device name and settings. - virtual void Create( - const std::string& camera_name, - const PlatformMediaSettings& settings, - std::function reply)> result) = 0; + virtual void Create(const std::string& camera_name, + const PlatformMediaSettings& settings, + std::function reply)> result) = 0; // Initializes a camera, and returns the size of its preview. virtual void Initialize( - int64_t camera_id, - std::function reply)> result) = 0; + int64_t camera_id, + std::function reply)> result) = 0; // Disposes a camera that is no longer in use. virtual std::optional Dispose(int64_t camera_id) = 0; // Takes a picture with the given camera, and returns the path to the // resulting file. virtual void TakePicture( - int64_t camera_id, - std::function reply)> result) = 0; + int64_t camera_id, + std::function reply)> result) = 0; // Starts recording video with the given camera. virtual void StartVideoRecording( - int64_t camera_id, - std::function reply)> result) = 0; + int64_t camera_id, + std::function reply)> result) = 0; // Finishes recording video with the given camera, and returns the path to // the resulting file. virtual void StopVideoRecording( - int64_t camera_id, - std::function reply)> result) = 0; + int64_t camera_id, + std::function reply)> result) = 0; // Starts the image stream for the given camera. virtual void StartImageStream( - int64_t camera_id, - std::function reply)> result) = 0; + int64_t camera_id, + std::function reply)> result) = 0; // Stops the image stream for the given camera. virtual void StopImageStream( - int64_t camera_id, - std::function reply)> result) = 0; + int64_t camera_id, + std::function reply)> result) = 0; // Starts the preview stream for the given camera. virtual void PausePreview( - int64_t camera_id, - std::function reply)> result) = 0; + int64_t camera_id, + std::function reply)> result) = 0; // Resumes the preview stream for the given camera. virtual void ResumePreview( - int64_t camera_id, - std::function reply)> result) = 0; + int64_t camera_id, + std::function reply)> result) = 0; // The codec used by CameraApi. static const flutter::StandardMessageCodec& GetCodec(); - // Sets up an instance of `CameraApi` to handle messages through the `binary_messenger`. - static void SetUp( - flutter::BinaryMessenger* binary_messenger, - CameraApi* api); - static void SetUp( - flutter::BinaryMessenger* binary_messenger, - CameraApi* api, - const std::string& message_channel_suffix); + // Sets up an instance of `CameraApi` to handle messages through the + // `binary_messenger`. + static void SetUp(flutter::BinaryMessenger* binary_messenger, CameraApi* api); + static void SetUp(flutter::BinaryMessenger* binary_messenger, CameraApi* api, + const std::string& message_channel_suffix); static flutter::EncodableValue WrapError(std::string_view error_message); static flutter::EncodableValue WrapError(const FlutterError& error); protected: CameraApi() = default; - }; } // namespace camera_windows #endif // PIGEON_MESSAGES_G_H_ diff --git a/packages/camera/camera_windows/windows/test/mocks.h b/packages/camera/camera_windows/windows/test/mocks.h index b4f08d075126..4d9556e1bf3e 100644 --- a/packages/camera/camera_windows/windows/test/mocks.h +++ b/packages/camera/camera_windows/windows/test/mocks.h @@ -248,9 +248,10 @@ class MockCaptureController : public CaptureController { MOCK_METHOD(void, PausePreview, (), (override)); MOCK_METHOD(void, StartRecord, (const std::string& file_path), (override)); MOCK_METHOD(void, StopRecord, (), (override)); - MOCK_METHOD(void, StartImageStream, - (std::unique_ptr> sink), - (override)); + MOCK_METHOD( + void, StartImageStream, + (std::unique_ptr> sink), + (override)); MOCK_METHOD(void, StopImageStream, (), (override)); MOCK_METHOD(void, TakePicture, (const std::string& file_path), (override)); }; From 82fa269a829a594399b2892a06c954136c5693d1 Mon Sep 17 00:00:00 2001 From: jlundOverlay Date: Fri, 26 Jul 2024 07:53:20 +0930 Subject: [PATCH 10/16] Update packages/camera/camera_windows/windows/camera_plugin.cpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Loïc Sharma <737941+loic-sharma@users.noreply.github.com> --- packages/camera/camera_windows/windows/camera_plugin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/camera/camera_windows/windows/camera_plugin.cpp b/packages/camera/camera_windows/windows/camera_plugin.cpp index 67a896a6372d..5a1aa2fdb4ca 100644 --- a/packages/camera/camera_windows/windows/camera_plugin.cpp +++ b/packages/camera/camera_windows/windows/camera_plugin.cpp @@ -397,9 +397,9 @@ void CameraPlugin::StopImageStream( if (!camera) { return result(FlutterError("camera_error", "Camera not created")); } - if (camera->HasPendingResultByType(PendingResultType::kStartStream)) { + if (camera->HasPendingResultByType(PendingResultType::kStopStream)) { return result( - FlutterError("camera_error", "Pending start stream request exists")); + FlutterError("camera_error", "Pending stop stream request exists")); } if (!event_sink) { From 0385677307eda12c3358cc8ab6442980b3a6ba71 Mon Sep 17 00:00:00 2001 From: Jacob Lund Date: Fri, 26 Jul 2024 08:00:06 +0930 Subject: [PATCH 11/16] remove redundant code and fix stopStreaming --- packages/camera/camera_windows/windows/camera_plugin.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/camera/camera_windows/windows/camera_plugin.cpp b/packages/camera/camera_windows/windows/camera_plugin.cpp index 5a1aa2fdb4ca..a7437f444338 100644 --- a/packages/camera/camera_windows/windows/camera_plugin.cpp +++ b/packages/camera/camera_windows/windows/camera_plugin.cpp @@ -402,12 +402,7 @@ void CameraPlugin::StopImageStream( FlutterError("camera_error", "Pending stop stream request exists")); } - if (!event_sink) { - return result(FlutterError("camera_error", - "Unable to make event channel from windows")); - } - - if (camera->AddPendingVoidResult(PendingResultType::kStartStream, + if (camera->AddPendingVoidResult(PendingResultType::kStopStream, std::move(result))) { CaptureController* cc = camera->GetCaptureController(); assert(cc); From 7c8fc81e885d5f53656db8f0054ff1a3ba09822e Mon Sep 17 00:00:00 2001 From: Jacob Lund Date: Fri, 26 Jul 2024 08:03:34 +0930 Subject: [PATCH 12/16] rollback camera versions --- packages/camera/camera/CHANGELOG.md | 4 ---- packages/camera/camera/lib/src/camera_controller.dart | 3 +-- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md index b9571baaddd8..53a6c4ca1ad8 100644 --- a/packages/camera/camera/CHANGELOG.md +++ b/packages/camera/camera/CHANGELOG.md @@ -1,7 +1,3 @@ -## 0.11.1 - -* Added support for image streaming to `camera_windows`. - ## 0.11.0+1 * Updates minimum supported SDK version to Flutter 3.16/Dart 3.2. diff --git a/packages/camera/camera/lib/src/camera_controller.dart b/packages/camera/camera/lib/src/camera_controller.dart index f9b797d459d7..5f90a0a740a9 100644 --- a/packages/camera/camera/lib/src/camera_controller.dart +++ b/packages/camera/camera/lib/src/camera_controller.dart @@ -486,8 +486,7 @@ class CameraController extends ValueNotifier { // TODO(bmparr): Add settings for resolution and fps. Future startImageStream(onLatestImageAvailable onAvailable) async { assert(defaultTargetPlatform == TargetPlatform.android || - defaultTargetPlatform == TargetPlatform.iOS || - defaultTargetPlatform == TargetPlatform.windows); + defaultTargetPlatform == TargetPlatform.iOS); _throwIfNotInitialized('startImageStream'); if (value.isRecordingVideo) { throw CameraException( From 8c91e68b8c530750e6f64cb5c2703ee0164a8592 Mon Sep 17 00:00:00 2001 From: Jacob Lund Date: Fri, 26 Jul 2024 08:08:55 +0930 Subject: [PATCH 13/16] missed one --- packages/camera/camera/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera/pubspec.yaml b/packages/camera/camera/pubspec.yaml index 6564581baeee..f00a7e798f01 100644 --- a/packages/camera/camera/pubspec.yaml +++ b/packages/camera/camera/pubspec.yaml @@ -4,7 +4,7 @@ description: A Flutter plugin for controlling the camera. Supports previewing Dart. 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 -version: 0.11.1 +version: 0.11.0+1 environment: sdk: ^3.2.3 From 0b59bfda44e88cf47f576c38f82597b405b84bc8 Mon Sep 17 00:00:00 2001 From: Jacob Lund Date: Fri, 26 Jul 2024 11:01:00 +0930 Subject: [PATCH 14/16] adds unit tests and a helper function --- .../camera_windows/windows/camera_plugin.cpp | 10 +- .../camera_windows/windows/camera_plugin.h | 2 + .../windows/test/camera_plugin_test.cpp | 226 ++++++++++++++++++ .../camera_windows/windows/test/mocks.h | 11 + 4 files changed, 247 insertions(+), 2 deletions(-) diff --git a/packages/camera/camera_windows/windows/camera_plugin.cpp b/packages/camera/camera_windows/windows/camera_plugin.cpp index a7437f444338..4b2abe39d6ac 100644 --- a/packages/camera/camera_windows/windows/camera_plugin.cpp +++ b/packages/camera/camera_windows/windows/camera_plugin.cpp @@ -122,6 +122,12 @@ std::optional GetFilePathForVideo() { } } // namespace +// a setter for the event sink helpful for testing. +void CameraPlugin::SetEventSink( + std::unique_ptr> events) { + event_sink = std::move(events); +} + // static void CameraPlugin::RegisterWithRegistrar( flutter::PluginRegistrarWindows* registrar) { @@ -134,8 +140,8 @@ void CameraPlugin::RegisterWithRegistrar( auto event_channel_handler = std::make_unique>( - [](auto arguments, auto events) { - event_sink = std::move(events); + [plugin = plugin.get()](auto arguments, auto events) { + plugin->SetEventSink(std::move(events)); return nullptr; }, [](auto arguments) { diff --git a/packages/camera/camera_windows/windows/camera_plugin.h b/packages/camera/camera_windows/windows/camera_plugin.h index 185772269f30..f77711402bb0 100644 --- a/packages/camera/camera_windows/windows/camera_plugin.h +++ b/packages/camera/camera_windows/windows/camera_plugin.h @@ -31,6 +31,8 @@ class CameraPlugin : public flutter::Plugin, public CameraApi, public VideoCaptureDeviceEnumerator { public: + void SetEventSink( + std::unique_ptr> events); static void RegisterWithRegistrar(flutter::PluginRegistrarWindows* registrar); CameraPlugin(flutter::TextureRegistrar* texture_registrar, diff --git a/packages/camera/camera_windows/windows/test/camera_plugin_test.cpp b/packages/camera/camera_windows/windows/test/camera_plugin_test.cpp index 2680ae26c0e3..6bd59dbde8a4 100644 --- a/packages/camera/camera_windows/windows/test/camera_plugin_test.cpp +++ b/packages/camera/camera_windows/windows/test/camera_plugin_test.cpp @@ -351,6 +351,232 @@ TEST(CameraPlugin, InitializeHandlerCallStartPreview) { EXPECT_TRUE(result_called); } +TEST(CameraPlugin, StartImageStreamHandlerCallsStartImageStream) { + int64_t mock_camera_id = 1234; + + std::unique_ptr camera = + std::make_unique(MOCK_DEVICE_ID); + + std::unique_ptr capture_controller = + std::make_unique(); + + EXPECT_CALL(*camera, HasCameraId(Eq(mock_camera_id))) + .Times(1) + .WillOnce([cam = camera.get()](int64_t camera_id) { + return cam->camera_id_ == camera_id; + }); + + EXPECT_CALL(*camera, + HasPendingResultByType(Eq(PendingResultType::kStartStream))) + .Times(1) + .WillOnce(Return(false)); + + EXPECT_CALL(*camera, + AddPendingVoidResult(Eq(PendingResultType::kStartStream), _)) + .Times(1) + .WillOnce([cam = camera.get()]( + PendingResultType type, + std::function)> result) { + cam->pending_void_result_ = std::move(result); + return true; + }); + + EXPECT_CALL(*camera, GetCaptureController) + .Times(1) + .WillOnce([cam = camera.get()]() { + assert(cam->pending_void_result_); + return cam->capture_controller_.get(); + }); + + EXPECT_CALL(*capture_controller, StartImageStream) + .Times(1) + .WillOnce([cam = camera.get()]() { + assert(cam->pending_void_result_); + return cam->pending_void_result_(std::nullopt); + }); + + camera->camera_id_ = mock_camera_id; + camera->capture_controller_ = std::move(capture_controller); + + MockCameraPlugin plugin(std::make_unique().get(), + std::make_unique().get(), + std::make_unique()); + + // Add mocked camera to plugins camera list. + plugin.AddCamera(std::move(camera)); + + // Set the event sink to a mocked event sink. + auto mock_event_sink = std::make_unique(); + plugin.SetEventSink(std::move(mock_event_sink)); + + bool result_called = false; + std::function)> start_image_stream_result = + [&result_called](std::optional reply) { + EXPECT_FALSE(result_called); // Ensure only one reply call. + result_called = true; + EXPECT_FALSE(reply); + }; + + plugin.StartImageStream(mock_camera_id, std::move(start_image_stream_result)); + + EXPECT_TRUE(result_called); +} + +TEST(CameraPlugin, StartImageStreamHandlerErrorOnInvalidCameraId) { + int64_t mock_camera_id = 1234; + int64_t missing_camera_id = 5678; + + std::unique_ptr camera = + std::make_unique(MOCK_DEVICE_ID); + + std::unique_ptr capture_controller = + std::make_unique(); + + EXPECT_CALL(*camera, HasCameraId) + .Times(1) + .WillOnce([cam = camera.get()](int64_t camera_id) { + return cam->camera_id_ == camera_id; + }); + + EXPECT_CALL(*camera, HasPendingResultByType).Times(0); + EXPECT_CALL(*camera, AddPendingVoidResult).Times(0); + EXPECT_CALL(*camera, GetCaptureController).Times(0); + EXPECT_CALL(*capture_controller, StartImageStream).Times(0); + + camera->camera_id_ = mock_camera_id; + + MockCameraPlugin plugin(std::make_unique().get(), + std::make_unique().get(), + std::make_unique()); + + // Add mocked camera to plugins camera list. + plugin.AddCamera(std::move(camera)); + + bool result_called = false; + std::function)> start_image_stream_result = + [&result_called](std::optional reply) { + EXPECT_FALSE(result_called); // Ensure only one reply call. + result_called = true; + EXPECT_TRUE(reply); + }; + + plugin.StartImageStream(missing_camera_id, + std::move(start_image_stream_result)); + + EXPECT_TRUE(result_called); +} + +TEST(CameraPlugin, StopImageStreamHandlerCallsStopImageStream) { + int64_t mock_camera_id = 1234; + + std::unique_ptr camera = + std::make_unique(MOCK_DEVICE_ID); + + std::unique_ptr capture_controller = + std::make_unique(); + + EXPECT_CALL(*camera, HasCameraId(Eq(mock_camera_id))) + .Times(1) + .WillOnce([cam = camera.get()](int64_t camera_id) { + return cam->camera_id_ == camera_id; + }); + + EXPECT_CALL(*camera, + HasPendingResultByType(Eq(PendingResultType::kStopStream))) + .Times(1) + .WillOnce(Return(false)); + + EXPECT_CALL(*camera, + AddPendingVoidResult(Eq(PendingResultType::kStopStream), _)) + .Times(1) + .WillOnce([cam = camera.get()]( + PendingResultType type, + std::function)> result) { + cam->pending_void_result_ = std::move(result); + return true; + }); + + EXPECT_CALL(*camera, GetCaptureController) + .Times(1) + .WillOnce([cam = camera.get()]() { + assert(cam->pending_void_result_); + return cam->capture_controller_.get(); + }); + + EXPECT_CALL(*capture_controller, StopImageStream) + .Times(1) + .WillOnce([cam = camera.get()]() { + assert(cam->pending_void_result_); + return cam->pending_void_result_(std::nullopt); + }); + + camera->camera_id_ = mock_camera_id; + camera->capture_controller_ = std::move(capture_controller); + + MockCameraPlugin plugin(std::make_unique().get(), + std::make_unique().get(), + std::make_unique()); + + // Add mocked camera to plugins camera list. + plugin.AddCamera(std::move(camera)); + + bool result_called = false; + std::function)> stop_image_stream_result = + [&result_called](std::optional reply) { + EXPECT_FALSE(result_called); // Ensure only one reply call. + result_called = true; + EXPECT_FALSE(reply); + }; + + plugin.StopImageStream(mock_camera_id, std::move(stop_image_stream_result)); + + EXPECT_TRUE(result_called); +} + +TEST(CameraPlugin, StopImageStreamHandlerErrorOnInvalidCameraId) { + int64_t mock_camera_id = 1234; + int64_t missing_camera_id = 5678; + + std::unique_ptr camera = + std::make_unique(MOCK_DEVICE_ID); + + std::unique_ptr capture_controller = + std::make_unique(); + + EXPECT_CALL(*camera, HasCameraId) + .Times(1) + .WillOnce([cam = camera.get()](int64_t camera_id) { + return cam->camera_id_ == camera_id; + }); + + EXPECT_CALL(*camera, HasPendingResultByType).Times(0); + EXPECT_CALL(*camera, AddPendingVoidResult).Times(0); + EXPECT_CALL(*camera, GetCaptureController).Times(0); + EXPECT_CALL(*capture_controller, StopImageStream).Times(0); + + camera->camera_id_ = mock_camera_id; + + MockCameraPlugin plugin(std::make_unique().get(), + std::make_unique().get(), + std::make_unique()); + + // Add mocked camera to plugins camera list. + plugin.AddCamera(std::move(camera)); + + bool result_called = false; + std::function)> stop_image_stream_result = + [&result_called](std::optional reply) { + EXPECT_FALSE(result_called); // Ensure only one reply call. + result_called = true; + EXPECT_TRUE(reply); + }; + + plugin.StopImageStream(missing_camera_id, + std::move(stop_image_stream_result)); + + EXPECT_TRUE(result_called); +} + TEST(CameraPlugin, InitializeHandlerErrorOnInvalidCameraId) { int64_t mock_camera_id = 1234; int64_t missing_camera_id = 5678; diff --git a/packages/camera/camera_windows/windows/test/mocks.h b/packages/camera/camera_windows/windows/test/mocks.h index 4d9556e1bf3e..85de158019dd 100644 --- a/packages/camera/camera_windows/windows/test/mocks.h +++ b/packages/camera/camera_windows/windows/test/mocks.h @@ -1076,6 +1076,17 @@ class MockCaptureEngine : public IMFCaptureEngine { volatile ULONG ref_ = 0; bool initialized_ = false; }; +// Mock class for flutter::EventSink +class MockEventSink : public flutter::EventSink { + public: + MOCK_METHOD(void, SuccessInternal, (const flutter::EncodableValue* event), + (override)); + MOCK_METHOD(void, ErrorInternal, + (const std::string& error_code, const std::string& error_message, + const flutter::EncodableValue* error_details), + (override)); + MOCK_METHOD(void, EndOfStreamInternal, (), (override)); +}; #define MOCK_DEVICE_ID "mock_device_id" #define MOCK_CAMERA_NAME "mock_camera_name <" MOCK_DEVICE_ID ">" From b20f69c4992ef9440006e6563554c3f0c31d42f8 Mon Sep 17 00:00:00 2001 From: Jacob Lund Date: Fri, 26 Jul 2024 11:05:13 +0930 Subject: [PATCH 15/16] missed one --- packages/camera/camera_windows/windows/test/mocks.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/camera/camera_windows/windows/test/mocks.h b/packages/camera/camera_windows/windows/test/mocks.h index 85de158019dd..be4f5358137e 100644 --- a/packages/camera/camera_windows/windows/test/mocks.h +++ b/packages/camera/camera_windows/windows/test/mocks.h @@ -248,10 +248,7 @@ class MockCaptureController : public CaptureController { MOCK_METHOD(void, PausePreview, (), (override)); MOCK_METHOD(void, StartRecord, (const std::string& file_path), (override)); MOCK_METHOD(void, StopRecord, (), (override)); - MOCK_METHOD( - void, StartImageStream, - (std::unique_ptr> sink), - (override)); + MOCK_METHOD(void, StartImageStream, (), (override)); MOCK_METHOD(void, StopImageStream, (), (override)); MOCK_METHOD(void, TakePicture, (const std::string& file_path), (override)); }; From e088f167bf973e0b27b5ad78695eb144480f4bdc Mon Sep 17 00:00:00 2001 From: Jacob Lund Date: Fri, 26 Jul 2024 11:07:17 +0930 Subject: [PATCH 16/16] wrong function --- packages/camera/camera_windows/windows/test/mocks.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/camera/camera_windows/windows/test/mocks.h b/packages/camera/camera_windows/windows/test/mocks.h index be4f5358137e..85de158019dd 100644 --- a/packages/camera/camera_windows/windows/test/mocks.h +++ b/packages/camera/camera_windows/windows/test/mocks.h @@ -248,7 +248,10 @@ class MockCaptureController : public CaptureController { MOCK_METHOD(void, PausePreview, (), (override)); MOCK_METHOD(void, StartRecord, (const std::string& file_path), (override)); MOCK_METHOD(void, StopRecord, (), (override)); - MOCK_METHOD(void, StartImageStream, (), (override)); + MOCK_METHOD( + void, StartImageStream, + (std::unique_ptr> sink), + (override)); MOCK_METHOD(void, StopImageStream, (), (override)); MOCK_METHOD(void, TakePicture, (const std::string& file_path), (override)); };