-
Notifications
You must be signed in to change notification settings - Fork 3k
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
[camera_windows] Support image streams on Windows platform #7067
Changes from all commits
7a2a0fa
99ae0e4
d553119
a89cf54
20c6192
753e28f
d48c932
f694dbe
b725973
fa007d7
9bfbfd6
404488d
dfa486c
76f0360
8a1dfc1
82fa269
0385677
7c8fc81
8c91e68
0b59bfd
b20f69c
e088f16
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
## 0.2.5 | ||
|
||
* Adds support for streaming frames. | ||
|
||
## 0.2.4+1 | ||
|
||
* Updates to pigeon 21. | ||
|
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>[ | ||
CameraImagePlane( | ||
bytes: data['data'] as Uint8List, | ||
bytesPerRow: (data['width'] as int) * 4, | ||
) | ||
]); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,8 @@ | |
|
||
#include "camera_plugin.h" | ||
|
||
#include <flutter/event_channel.h> | ||
#include <flutter/event_stream_handler_functions.h> | ||
#include <flutter/flutter_view.h> | ||
#include <flutter/method_channel.h> | ||
#include <flutter/plugin_registrar_windows.h> | ||
|
@@ -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<flutter::EventSink<flutter::EncodableValue>> event_sink; | ||
|
||
// Builds CaptureDeviceInfo object from given device holding device name and id. | ||
std::unique_ptr<CaptureDeviceInfo> GetDeviceInfo(IMFActivate* device) { | ||
|
@@ -116,12 +122,34 @@ std::optional<std::string> GetFilePathForVideo() { | |
} | ||
} // namespace | ||
|
||
// a setter for the event sink helpful for testing. | ||
void CameraPlugin::SetEventSink( | ||
std::unique_ptr<flutter::EventSink<flutter::EncodableValue>> events) { | ||
event_sink = std::move(events); | ||
} | ||
|
||
// static | ||
void CameraPlugin::RegisterWithRegistrar( | ||
flutter::PluginRegistrarWindows* registrar) { | ||
std::unique_ptr<CameraPlugin> plugin = std::make_unique<CameraPlugin>( | ||
registrar->texture_registrar(), registrar->messenger()); | ||
|
||
auto frameEventchannel = std::make_unique<flutter::EventChannel<>>( | ||
registrar->messenger(), kFrameEventChannelName, | ||
&flutter::StandardMethodCodec::GetInstance()); | ||
|
||
auto event_channel_handler = | ||
std::make_unique<flutter::StreamHandlerFunctions<>>( | ||
[plugin = plugin.get()](auto arguments, auto events) { | ||
plugin->SetEventSink(std::move(events)); | ||
return nullptr; | ||
}, | ||
[](auto arguments) { | ||
event_sink.reset(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 Given the scope of issues here, I'm going to revert this. @cbracken FYI. |
||
return nullptr; | ||
}); | ||
frameEventchannel->SetStreamHandler(std::move(event_channel_handler)); | ||
|
||
CameraApi::SetUp(registrar->messenger(), plugin.get()); | ||
|
||
registrar->AddPlugin(std::move(plugin)); | ||
|
@@ -341,6 +369,53 @@ void CameraPlugin::StopVideoRecording( | |
} | ||
} | ||
|
||
void CameraPlugin::StartImageStream( | ||
int64_t camera_id, | ||
std::function<void(std::optional<FlutterError> 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")); | ||
} | ||
|
||
jlundOverlay marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (camera->AddPendingVoidResult(PendingResultType::kStartStream, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where are the pending results added in this PR resolved? I don't see anything in the diff that retrieves them. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good question, when i wrote it figured id deal with that later and forgot. What exactly are these checks used for and are they necessary if the function is synchronous? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There will be no result object if the API is made synchronous. |
||
std::move(result))) { | ||
CaptureController* cc = camera->GetCaptureController(); | ||
assert(cc); | ||
cc->StartImageStream(std::move(event_sink)); | ||
} | ||
} | ||
|
||
void CameraPlugin::StopImageStream( | ||
int64_t camera_id, | ||
std::function<void(std::optional<FlutterError> 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::kStopStream)) { | ||
return result( | ||
FlutterError("camera_error", "Pending stop stream request exists")); | ||
} | ||
|
||
if (camera->AddPendingVoidResult(PendingResultType::kStopStream, | ||
std::move(result))) { | ||
CaptureController* cc = camera->GetCaptureController(); | ||
assert(cc); | ||
cc->StopImageStream(); | ||
} | ||
} | ||
|
||
void CameraPlugin::TakePicture( | ||
int64_t camera_id, std::function<void(ErrorOr<std::string> reply)> result) { | ||
auto camera = GetCameraByCameraId(camera_id); | ||
|
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.
Why are these
@async
? It looks like the logic is synchronous.