-
Notifications
You must be signed in to change notification settings - Fork 3.6k
[camera_windows] Support image streams on Windows platform #7067
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 3 commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
7a2a0fa
Adds actual windows support for streaming bgra frames to the flutter …
jlundOverlay 99ae0e4
add windows as an option for streaming frames
jlundOverlay d553119
Merge branch 'main' into main
jlundOverlay a89cf54
apply suggested format changes
jlundOverlay 20c6192
change to explict types
jlundOverlay 753e28f
Merge branch 'local_main'
jlundOverlay d48c932
Migrated streaming to pigeon
jlundOverlay f694dbe
Merge branch 'main' into main
jlundOverlay b725973
accepted the wrong changes
jlundOverlay fa007d7
Merge branch 'main' into main
jlundOverlay 9bfbfd6
Merge branch 'main' into main
jlundOverlay 404488d
Merge branch 'main' into main
jlundOverlay dfa486c
hopefully this is right
jlundOverlay 76f0360
bump camera version
jlundOverlay 8a1dfc1
formatting fixes
jlundOverlay 82fa269
Update packages/camera/camera_windows/windows/camera_plugin.cpp
jlundOverlay 0385677
remove redundant code and fix stopStreaming
jlundOverlay 7c8fc81
rollback camera versions
jlundOverlay 8c91e68
missed one
jlundOverlay 0b59bfd
adds unit tests and a helper function
jlundOverlay b20f69c
missed one
jlundOverlay e088f16
wrong function
jlundOverlay File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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<dynamic, dynamic> 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), | ||
| ) | ||
| ]); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,8 +6,10 @@ | |
|
|
||
| #include <flutter/flutter_view.h> | ||
| #include <flutter/method_channel.h> | ||
| #include <flutter/event_channel.h> | ||
| #include <flutter/plugin_registrar_windows.h> | ||
| #include <flutter/standard_method_codec.h> | ||
| #include <flutter/event_stream_handler_functions.h> | ||
| #include <mfapi.h> | ||
| #include <mfidl.h> | ||
| #include <shlobj.h> | ||
|
|
@@ -18,6 +20,8 @@ | |
| #include <chrono> | ||
| #include <memory> | ||
|
|
||
| #include <iostream> | ||
|
|
||
| #include "capture_device_info.h" | ||
| #include "com_heap_ptr.h" | ||
| #include "string_utils.h" | ||
|
|
@@ -31,13 +35,17 @@ 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"; | ||
| 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<flutter::EventSink<flutter::EncodableValue>> 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<flutter::MethodChannel<>>( | ||
| registrar->messenger(), kChannelName, | ||
| &flutter::StandardMethodCodec::GetInstance()); | ||
| auto frameEventchannel = std::make_unique<flutter::EventChannel<>>( | ||
| registrar->messenger(), kFrameEventChannelName, | ||
| &flutter::StandardMethodCodec::GetInstance()); | ||
|
|
||
| std::unique_ptr<CameraPlugin> plugin = std::make_unique<CameraPlugin>( | ||
| 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<flutter::StreamHandlerFunctions<>>( | ||
| [](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<flutter::EncodableMap>(method_call.arguments()); | ||
| assert(arguments); | ||
|
|
||
| return StartImageStreamingMethodHandler(*arguments, std::move(result)); | ||
| }else if (method_name.compare(kStopImageStreamingMethod) == 0) { | ||
jlundOverlay marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| const auto* arguments = | ||
| std::get_if<flutter::EncodableMap>(method_call.arguments()); | ||
| assert(arguments); | ||
|
|
||
| return StopImageStreamingMethodHandler(*arguments, std::move(result)); | ||
| }else if (method_name.compare(kPausePreview) == 0) { | ||
jlundOverlay marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| const auto* arguments = | ||
| std::get_if<flutter::EncodableMap>(method_call.arguments()); | ||
| assert(arguments); | ||
|
|
@@ -569,6 +604,66 @@ void CameraPlugin::StopVideoRecordingMethodHandler( | |
| cc->StopRecord(); | ||
| } | ||
| } | ||
| void CameraPlugin::StartImageStreamingMethodHandler( | ||
| const EncodableMap& args, std::unique_ptr<flutter::MethodResult<>> result) { | ||
| auto camera_id = GetInt64ValueOrNull(args, kCameraIdKey); //get camera id | ||
cbracken marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| 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)); | ||
| } | ||
|
|
||
|
|
||
jlundOverlay marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| void CameraPlugin::StopImageStreamingMethodHandler( | ||
jlundOverlay marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| const EncodableMap& args, std::unique_ptr<flutter::MethodResult<>> 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<flutter::MethodResult<>> result) { | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was going to do a quick fix to the issues I raised in my previous comments, but then I noticed the code related to
event_sink. This is a global, which is already very dangerous, but it's alsostd::moved between classes while still being referenced persistently in both. This code would likely fail the second time an image stream was started, and would absolutely fail with multiple engines.Given the scope of issues here, I'm going to revert this. @cbracken FYI.