diff --git a/packages/camera/camera_windows/lib/camera_windows.dart b/packages/camera/camera_windows/lib/camera_windows.dart index bdbfc17dcf8e..8714163344e1 100644 --- a/packages/camera/camera_windows/lib/camera_windows.dart +++ b/packages/camera/camera_windows/lib/camera_windows.dart @@ -133,6 +133,7 @@ class CameraWindows extends CameraPlatform { @override Future dispose(int cameraId) async { + await _stopPlatformStream(cameraId); await _hostApi.dispose(cameraId); // Destroy method channel after camera is disposed to be able to handle last messages. @@ -266,13 +267,14 @@ class CameraWindows extends CameraPlatform { } Future _startPlatformStream(int cameraId) async { - _startStreamListener(); await _hostApi.startImageStream(cameraId); + _startStreamListener(cameraId); } - void _startStreamListener() { - const EventChannel cameraEventChannel = - EventChannel('plugins.flutter.io/camera_android/imageStream'); + void _startStreamListener(int cameraId) { + final eventChannelName = + 'plugins.flutter.io/camera_windows/imageStream/$cameraId'; + final EventChannel cameraEventChannel = EventChannel(eventChannelName); _platformImageStreamSubscription = cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { _frameStreamController! @@ -281,6 +283,10 @@ class CameraWindows extends CameraPlatform { } FutureOr _onFrameStreamCancel(int cameraId) async { + await _stopPlatformStream(cameraId); + } + + Future _stopPlatformStream(int cameraId) async { await _hostApi.stopImageStream(cameraId); await _platformImageStreamSubscription?.cancel(); _platformImageStreamSubscription = null; diff --git a/packages/camera/camera_windows/windows/camera_plugin.cpp b/packages/camera/camera_windows/windows/camera_plugin.cpp index c3eb02a7db3d..f727670b8cd7 100644 --- a/packages/camera/camera_windows/windows/camera_plugin.cpp +++ b/packages/camera/camera_windows/windows/camera_plugin.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include "capture_device_info.h" #include "com_heap_ptr.h" @@ -35,10 +36,6 @@ 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) { @@ -123,34 +120,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) { 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>( - [plugin = plugin.get()](auto arguments, auto events) { - plugin->SetEventSink(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)); @@ -377,14 +352,29 @@ std::optional CameraPlugin::StartImageStream(int64_t camera_id) { return FlutterError("camera_error", "Camera not created"); } - if (!event_sink) { - return FlutterError("camera_error", - "Unable to make event channel from windows"); - } - CaptureController* cc = camera->GetCaptureController(); assert(cc); - cc->StartImageStream(std::move(event_sink)); + + std::ostringstream event_channel_name; + event_channel_name << "plugins.flutter.io/camera_windows/imageStream/" + << camera_id; + + auto frame_event_channel = + flutter::EventChannel(messenger_, event_channel_name.str(), + &flutter::StandardMethodCodec::GetInstance()); + + auto event_channel_handler = + std::make_unique>( + [cc](auto arguments, auto events) { + cc->StartImageStream(std::move(events)); + return nullptr; + }, + [cc](auto arguments) { + cc->StopImageStream(); + return nullptr; + }); + + frame_event_channel.SetStreamHandler(std::move(event_channel_handler)); return std::nullopt; } diff --git a/packages/camera/camera_windows/windows/camera_plugin.h b/packages/camera/camera_windows/windows/camera_plugin.h index 144f2434aae3..3f901e3f017d 100644 --- a/packages/camera/camera_windows/windows/camera_plugin.h +++ b/packages/camera/camera_windows/windows/camera_plugin.h @@ -32,8 +32,6 @@ 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 06626a2c35c3..4509a888cce3 100644 --- a/packages/camera/camera_windows/windows/test/camera_plugin_test.cpp +++ b/packages/camera/camera_windows/windows/test/camera_plugin_test.cpp @@ -27,10 +27,10 @@ using ::testing::_; using ::testing::DoAll; using ::testing::EndsWith; using ::testing::Eq; -using ::testing::Pointee; -using ::testing::Return; using ::testing::Optional; +using ::testing::Pointee; using ::testing::Property; +using ::testing::Return; void MockInitCamera(MockCamera* camera, bool success) { EXPECT_CALL(*camera, @@ -371,12 +371,10 @@ TEST(CameraPlugin, StartImageStreamHandlerCallsStartImageStream) { EXPECT_CALL(*camera, GetCaptureController) .Times(1) - .WillOnce([cam = camera.get()]() { - return cam->capture_controller_.get(); - }); + .WillOnce( + [cam = camera.get()]() { return cam->capture_controller_.get(); }); - EXPECT_CALL(*capture_controller, StartImageStream) - .Times(1); + EXPECT_CALL(*capture_controller, StartImageStream).Times(1); camera->camera_id_ = mock_camera_id; camera->capture_controller_ = std::move(capture_controller); @@ -385,10 +383,6 @@ TEST(CameraPlugin, StartImageStreamHandlerCallsStartImageStream) { std::make_unique().get(), std::make_unique()); - // Set the event sink to a mocked event sink. - auto mock_event_sink = std::make_unique(); - plugin.SetEventSink(std::move(mock_event_sink)); - // Add mocked camera to plugins camera list. plugin.AddCamera(std::move(camera)); @@ -425,7 +419,8 @@ TEST(CameraPlugin, StartImageStreamHandlerErrorOnInvalidCameraId) { // Add mocked camera to plugins camera list. plugin.AddCamera(std::move(camera)); - EXPECT_THAT(plugin.StartImageStream(missing_camera_id), Optional(Property("code", &FlutterError::code, "camera_error"))); + EXPECT_THAT(plugin.StartImageStream(missing_camera_id), + Optional(Property("code", &FlutterError::code, "camera_error"))); } TEST(CameraPlugin, StopImageStreamHandlerCallsStopImageStream) { @@ -445,12 +440,10 @@ TEST(CameraPlugin, StopImageStreamHandlerCallsStopImageStream) { EXPECT_CALL(*camera, GetCaptureController) .Times(1) - .WillOnce([cam = camera.get()]() { - return cam->capture_controller_.get(); - }); + .WillOnce( + [cam = camera.get()]() { return cam->capture_controller_.get(); }); - EXPECT_CALL(*capture_controller, StopImageStream) - .Times(1); + EXPECT_CALL(*capture_controller, StopImageStream).Times(1); camera->camera_id_ = mock_camera_id; camera->capture_controller_ = std::move(capture_controller); @@ -495,7 +488,8 @@ TEST(CameraPlugin, StopImageStreamHandlerErrorOnInvalidCameraId) { // Add mocked camera to plugins camera list. plugin.AddCamera(std::move(camera)); - EXPECT_THAT(plugin.StopImageStream(missing_camera_id), Optional(Property("code", &FlutterError::code, "camera_error"))); + EXPECT_THAT(plugin.StopImageStream(missing_camera_id), + Optional(Property("code", &FlutterError::code, "camera_error"))); } TEST(CameraPlugin, InitializeHandlerErrorOnInvalidCameraId) {