Skip to content

Commit b3a5e33

Browse files
[camera_windows] Revert: Support image streams on Windows platform (flutter#7951)
This reverts commit b31a279 (flutter#7067) The implementation had significant bugs: - It had asynchronous results, but never responded to them, violating the engine API contract and preventing futures from completing. - It `std::move`d pointers between classes, while still keeping them as ivars and global references and referring to them from long-lived handlers.
1 parent 2c8f226 commit b3a5e33

File tree

15 files changed

+7
-605
lines changed

15 files changed

+7
-605
lines changed

packages/camera/camera_windows/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 0.2.6
2+
3+
* Reverts streaming frame support, as the implementation was incorrect and never
4+
exposed.
5+
16
## 0.2.5+1
27

38
* Updates C++ to Dart communication to use Pigeon.

packages/camera/camera_windows/lib/camera_windows.dart

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import 'package:flutter/widgets.dart';
1111
import 'package:stream_transform/stream_transform.dart';
1212

1313
import 'src/messages.g.dart';
14-
import 'type_conversion.dart';
1514

1615
/// An implementation of [CameraPlatform] for Windows.
1716
class CameraWindows extends CameraPlatform {
@@ -33,12 +32,6 @@ class CameraWindows extends CameraPlatform {
3332
final Map<int, HostCameraMessageHandler> hostCameraHandlers =
3433
<int, HostCameraMessageHandler>{};
3534

36-
// The stream to receive frames from the native code.
37-
StreamSubscription<dynamic>? _platformImageStreamSubscription;
38-
39-
// The stream for vending frames to platform interface clients.
40-
StreamController<CameraImageData>? _frameStreamController;
41-
4235
/// The controller that broadcasts events coming from handleCameraMethodCall
4336
///
4437
/// It is a `broadcast` because multiple controllers will connect to
@@ -241,57 +234,6 @@ class CameraWindows extends CameraPlatform {
241234
'resumeVideoRecording() is not supported due to Win32 API limitations.');
242235
}
243236

244-
@override
245-
Stream<CameraImageData> onStreamedFrameAvailable(int cameraId,
246-
{CameraImageStreamOptions? options}) {
247-
_installStreamController(
248-
onListen: () => _onFrameStreamListen(cameraId),
249-
onCancel: () => _onFrameStreamCancel(cameraId));
250-
return _frameStreamController!.stream;
251-
}
252-
253-
StreamController<CameraImageData> _installStreamController(
254-
{void Function()? onListen, void Function()? onCancel}) {
255-
_frameStreamController = StreamController<CameraImageData>(
256-
onListen: onListen ?? () {},
257-
onPause: _onFrameStreamPauseResume,
258-
onResume: _onFrameStreamPauseResume,
259-
onCancel: onCancel ?? () {},
260-
);
261-
return _frameStreamController!;
262-
}
263-
264-
void _onFrameStreamListen(int cameraId) {
265-
_startPlatformStream(cameraId);
266-
}
267-
268-
Future<void> _startPlatformStream(int cameraId) async {
269-
_startStreamListener();
270-
await _hostApi.startImageStream(cameraId);
271-
}
272-
273-
void _startStreamListener() {
274-
const EventChannel cameraEventChannel =
275-
EventChannel('plugins.flutter.io/camera_android/imageStream');
276-
_platformImageStreamSubscription =
277-
cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) {
278-
_frameStreamController!
279-
.add(cameraImageFromPlatformData(imageData as Map<dynamic, dynamic>));
280-
});
281-
}
282-
283-
FutureOr<void> _onFrameStreamCancel(int cameraId) async {
284-
await _hostApi.stopImageStream(cameraId);
285-
await _platformImageStreamSubscription?.cancel();
286-
_platformImageStreamSubscription = null;
287-
_frameStreamController = null;
288-
}
289-
290-
void _onFrameStreamPauseResume() {
291-
throw CameraException('InvalidCall',
292-
'Pause and resume are not supported for onStreamedFrameAvailable');
293-
}
294-
295237
@override
296238
Future<void> setFlashMode(int cameraId, FlashMode mode) async {
297239
// TODO(jokerttu): Implement flash mode support, https://github.com/flutter/flutter/issues/97537.

packages/camera/camera_windows/lib/src/messages.g.dart

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -362,56 +362,6 @@ class CameraApi {
362362
}
363363
}
364364

365-
/// Starts the image stream for the given camera.
366-
Future<void> startImageStream(int cameraId) async {
367-
final String pigeonVar_channelName =
368-
'dev.flutter.pigeon.camera_windows.CameraApi.startImageStream$pigeonVar_messageChannelSuffix';
369-
final BasicMessageChannel<Object?> pigeonVar_channel =
370-
BasicMessageChannel<Object?>(
371-
pigeonVar_channelName,
372-
pigeonChannelCodec,
373-
binaryMessenger: pigeonVar_binaryMessenger,
374-
);
375-
final List<Object?>? pigeonVar_replyList =
376-
await pigeonVar_channel.send(<Object?>[cameraId]) as List<Object?>?;
377-
if (pigeonVar_replyList == null) {
378-
throw _createConnectionError(pigeonVar_channelName);
379-
} else if (pigeonVar_replyList.length > 1) {
380-
throw PlatformException(
381-
code: pigeonVar_replyList[0]! as String,
382-
message: pigeonVar_replyList[1] as String?,
383-
details: pigeonVar_replyList[2],
384-
);
385-
} else {
386-
return;
387-
}
388-
}
389-
390-
/// Stops the image stream for the given camera.
391-
Future<void> stopImageStream(int cameraId) async {
392-
final String pigeonVar_channelName =
393-
'dev.flutter.pigeon.camera_windows.CameraApi.stopImageStream$pigeonVar_messageChannelSuffix';
394-
final BasicMessageChannel<Object?> pigeonVar_channel =
395-
BasicMessageChannel<Object?>(
396-
pigeonVar_channelName,
397-
pigeonChannelCodec,
398-
binaryMessenger: pigeonVar_binaryMessenger,
399-
);
400-
final List<Object?>? pigeonVar_replyList =
401-
await pigeonVar_channel.send(<Object?>[cameraId]) as List<Object?>?;
402-
if (pigeonVar_replyList == null) {
403-
throw _createConnectionError(pigeonVar_channelName);
404-
} else if (pigeonVar_replyList.length > 1) {
405-
throw PlatformException(
406-
code: pigeonVar_replyList[0]! as String,
407-
message: pigeonVar_replyList[1] as String?,
408-
details: pigeonVar_replyList[2],
409-
);
410-
} else {
411-
return;
412-
}
413-
}
414-
415365
/// Starts the preview stream for the given camera.
416366
Future<void> pausePreview(int cameraId) async {
417367
final String pigeonVar_channelName =

packages/camera/camera_windows/lib/type_conversion.dart

Lines changed: 0 additions & 25 deletions
This file was deleted.

packages/camera/camera_windows/pigeons/messages.dart

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,6 @@ abstract class CameraApi {
7070
@async
7171
String stopVideoRecording(int cameraId);
7272

73-
/// Starts the image stream for the given camera.
74-
@async
75-
void startImageStream(int cameraId);
76-
77-
/// Stops the image stream for the given camera.
78-
@async
79-
void stopImageStream(int cameraId);
80-
8173
/// Starts the preview stream for the given camera.
8274
@async
8375
void pausePreview(int cameraId);

packages/camera/camera_windows/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: camera_windows
22
description: A Flutter plugin for getting information about and controlling the camera on Windows.
33
repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_windows
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22
5-
version: 0.2.5+1
5+
version: 0.2.6
66

77
environment:
88
sdk: ^3.3.0

packages/camera/camera_windows/windows/camera.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ enum class PendingResultType {
2222
kTakePicture,
2323
kStartRecord,
2424
kStopRecord,
25-
kStartStream,
26-
kStopStream,
2725
kPausePreview,
2826
kResumePreview,
2927
};

packages/camera/camera_windows/windows/camera_plugin.cpp

Lines changed: 0 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
#include "camera_plugin.h"
66

7-
#include <flutter/event_channel.h>
8-
#include <flutter/event_stream_handler_functions.h>
97
#include <flutter/flutter_view.h>
108
#include <flutter/method_channel.h>
119
#include <flutter/plugin_registrar_windows.h>
@@ -34,10 +32,6 @@ namespace {
3432

3533
const std::string kPictureCaptureExtension = "jpeg";
3634
const std::string kVideoCaptureExtension = "mp4";
37-
constexpr char kFrameEventChannelName[] =
38-
"plugins.flutter.io/camera_android/imageStream";
39-
40-
std::unique_ptr<flutter::EventSink<flutter::EncodableValue>> event_sink;
4135

4236
// Builds CaptureDeviceInfo object from given device holding device name and id.
4337
std::unique_ptr<CaptureDeviceInfo> GetDeviceInfo(IMFActivate* device) {
@@ -122,34 +116,12 @@ std::optional<std::string> GetFilePathForVideo() {
122116
}
123117
} // namespace
124118

125-
// a setter for the event sink helpful for testing.
126-
void CameraPlugin::SetEventSink(
127-
std::unique_ptr<flutter::EventSink<flutter::EncodableValue>> events) {
128-
event_sink = std::move(events);
129-
}
130-
131119
// static
132120
void CameraPlugin::RegisterWithRegistrar(
133121
flutter::PluginRegistrarWindows* registrar) {
134122
std::unique_ptr<CameraPlugin> plugin = std::make_unique<CameraPlugin>(
135123
registrar->texture_registrar(), registrar->messenger());
136124

137-
auto frameEventchannel = std::make_unique<flutter::EventChannel<>>(
138-
registrar->messenger(), kFrameEventChannelName,
139-
&flutter::StandardMethodCodec::GetInstance());
140-
141-
auto event_channel_handler =
142-
std::make_unique<flutter::StreamHandlerFunctions<>>(
143-
[plugin = plugin.get()](auto arguments, auto events) {
144-
plugin->SetEventSink(std::move(events));
145-
return nullptr;
146-
},
147-
[](auto arguments) {
148-
event_sink.reset();
149-
return nullptr;
150-
});
151-
frameEventchannel->SetStreamHandler(std::move(event_channel_handler));
152-
153125
CameraApi::SetUp(registrar->messenger(), plugin.get());
154126

155127
registrar->AddPlugin(std::move(plugin));
@@ -369,53 +341,6 @@ void CameraPlugin::StopVideoRecording(
369341
}
370342
}
371343

372-
void CameraPlugin::StartImageStream(
373-
int64_t camera_id,
374-
std::function<void(std::optional<FlutterError> reply)> result) {
375-
// check if request already exists
376-
Camera* camera = GetCameraByCameraId(camera_id);
377-
if (!camera) {
378-
return result(FlutterError("camera_error", "Camera not created"));
379-
}
380-
if (camera->HasPendingResultByType(PendingResultType::kStartStream)) {
381-
return result(
382-
FlutterError("camera_error", "Pending start stream request exists"));
383-
}
384-
385-
if (!event_sink) {
386-
return result(FlutterError("camera_error",
387-
"Unable to make event channel from windows"));
388-
}
389-
390-
if (camera->AddPendingVoidResult(PendingResultType::kStartStream,
391-
std::move(result))) {
392-
CaptureController* cc = camera->GetCaptureController();
393-
assert(cc);
394-
cc->StartImageStream(std::move(event_sink));
395-
}
396-
}
397-
398-
void CameraPlugin::StopImageStream(
399-
int64_t camera_id,
400-
std::function<void(std::optional<FlutterError> reply)> result) {
401-
// check if request already exists
402-
Camera* camera = GetCameraByCameraId(camera_id);
403-
if (!camera) {
404-
return result(FlutterError("camera_error", "Camera not created"));
405-
}
406-
if (camera->HasPendingResultByType(PendingResultType::kStopStream)) {
407-
return result(
408-
FlutterError("camera_error", "Pending stop stream request exists"));
409-
}
410-
411-
if (camera->AddPendingVoidResult(PendingResultType::kStopStream,
412-
std::move(result))) {
413-
CaptureController* cc = camera->GetCaptureController();
414-
assert(cc);
415-
cc->StopImageStream();
416-
}
417-
}
418-
419344
void CameraPlugin::TakePicture(
420345
int64_t camera_id, std::function<void(ErrorOr<std::string> reply)> result) {
421346
auto camera = GetCameraByCameraId(camera_id);

packages/camera/camera_windows/windows/camera_plugin.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ class CameraPlugin : public flutter::Plugin,
3131
public CameraApi,
3232
public VideoCaptureDeviceEnumerator {
3333
public:
34-
void SetEventSink(
35-
std::unique_ptr<flutter::EventSink<flutter::EncodableValue>> events);
3634
static void RegisterWithRegistrar(flutter::PluginRegistrarWindows* registrar);
3735

3836
CameraPlugin(flutter::TextureRegistrar* texture_registrar,
@@ -70,12 +68,6 @@ class CameraPlugin : public flutter::Plugin,
7068
void StopVideoRecording(
7169
int64_t camera_id,
7270
std::function<void(ErrorOr<std::string> reply)> result) override;
73-
void StartImageStream(
74-
int64_t camera_id,
75-
std::function<void(std::optional<FlutterError> reply)> result) override;
76-
void StopImageStream(
77-
int64_t camera_id,
78-
std::function<void(std::optional<FlutterError> reply)> result) override;
7971
void TakePicture(
8072
int64_t camera_id,
8173
std::function<void(ErrorOr<std::string> reply)> result) override;

packages/camera/camera_windows/windows/capture_controller.cpp

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,11 @@
55
#include "capture_controller.h"
66

77
#include <comdef.h>
8-
#include <flutter/event_stream_handler_functions.h>
9-
#include <flutter/standard_method_codec.h>
108
#include <wincodec.h>
119
#include <wrl/client.h>
1210

1311
#include <cassert>
1412
#include <chrono>
15-
#include <iostream>
1613

1714
#include "com_heap_ptr.h"
1815
#include "photo_handler.h"
@@ -553,16 +550,6 @@ void CaptureControllerImpl::StopRecord() {
553550
"Failed to stop video recording");
554551
}
555552
}
556-
void CaptureControllerImpl::StartImageStream(
557-
std::unique_ptr<flutter::EventSink<flutter::EncodableValue>> sink) {
558-
assert(capture_controller_listener_);
559-
image_stream_sink_ = std::move(sink);
560-
}
561-
562-
void CaptureControllerImpl::StopImageStream() {
563-
assert(capture_controller_listener_);
564-
image_stream_sink_.reset();
565-
}
566553

567554
// Starts capturing preview frames using preview handler
568555
// After first frame is captured, OnPreviewStarted is called
@@ -856,32 +843,6 @@ bool CaptureControllerImpl::UpdateBuffer(uint8_t* buffer,
856843
if (!texture_handler_) {
857844
return false;
858845
}
859-
if (image_stream_sink_) {
860-
// Convert the buffer data to a std::vector<uint8_t>.
861-
std::vector<uint8_t> buffer_data(buffer, buffer + data_length);
862-
863-
// Ensure preview_frame_height_ and preview_frame_width_ are of supported
864-
// types.
865-
int preview_frame_height = static_cast<int>(preview_frame_height_);
866-
int preview_frame_width = static_cast<int>(preview_frame_width_);
867-
868-
// Create a map to hold the buffer data and data length.
869-
flutter::EncodableMap data_map;
870-
data_map[flutter::EncodableValue("data")] =
871-
flutter::EncodableValue(buffer_data);
872-
data_map[flutter::EncodableValue("height")] =
873-
flutter::EncodableValue(preview_frame_height);
874-
data_map[flutter::EncodableValue("width")] =
875-
flutter::EncodableValue(preview_frame_width);
876-
data_map[flutter::EncodableValue("length")] =
877-
flutter::EncodableValue(static_cast<int>(data_length));
878-
879-
// Wrap the map in a flutter::EncodableValue.
880-
flutter::EncodableValue encoded_value(data_map);
881-
882-
// Send the encoded value through the image_stream_sink_.
883-
image_stream_sink_->Success(encoded_value);
884-
}
885846
return texture_handler_->UpdateBuffer(buffer, data_length);
886847
}
887848

0 commit comments

Comments
 (0)