From 34feab80cc43e3090e7d3a0d4b9a9ad62564fd31 Mon Sep 17 00:00:00 2001 From: Hidenori Matsubayashi Date: Tue, 17 Aug 2021 17:49:36 +0900 Subject: [PATCH] [camera] Source code refactoring (#31) Changes: * Source code refactoring * Add temporary code for camera image stream APIs --- packages/camera/README.md | 5 +- packages/camera/elinux/CMakeLists.txt | 5 +- .../camera/elinux/camera_elinux_plugin.cc | 79 ++++++++++++++----- .../camera/elinux/camera_stream_handler.h | 8 -- .../elinux/camera_stream_handler_impl.h | 26 +----- .../channels/event_channel_image_stream.cc | 72 +++++++++++++++++ .../channels/event_channel_image_stream.h | 27 +++++++ .../method_channel_camera.cc | 2 +- .../method_channel_camera.h | 12 +-- .../method_channel_device.cc | 2 +- .../method_channel_device.h | 6 +- 11 files changed, 173 insertions(+), 71 deletions(-) create mode 100644 packages/camera/elinux/channels/event_channel_image_stream.cc create mode 100644 packages/camera/elinux/channels/event_channel_image_stream.h rename packages/camera/elinux/{method_channel => channels}/method_channel_camera.cc (96%) rename packages/camera/elinux/{method_channel => channels}/method_channel_camera.h (70%) rename packages/camera/elinux/{method_channel => channels}/method_channel_device.cc (96%) rename packages/camera/elinux/{method_channel => channels}/method_channel_device.h (75%) diff --git a/packages/camera/README.md b/packages/camera/README.md index 4ecb235..3a47210 100644 --- a/packages/camera/README.md +++ b/packages/camera/README.md @@ -34,7 +34,7 @@ Import `camera` in your Dart code: import 'package:camera/camera.dart'; ``` -## Troubleshoting +## Troubleshooting If you get the following error: ```Shell @@ -43,5 +43,6 @@ Wrong JPEG library version: library is 62, caller expects 80 , try the following: ```Shell -sudo mv /usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstjpeg.so /usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstjpeg.so.org +sudo mv /usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstjpeg.so \ + /usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstjpeg.so.org ``` diff --git a/packages/camera/elinux/CMakeLists.txt b/packages/camera/elinux/CMakeLists.txt index 0369976..d649613 100644 --- a/packages/camera/elinux/CMakeLists.txt +++ b/packages/camera/elinux/CMakeLists.txt @@ -12,12 +12,13 @@ pkg_check_modules(GSTREAMER REQUIRED gstreamer-1.0) add_library(${PLUGIN_NAME} SHARED "camera_elinux_plugin.cc" + "channels/event_channel_image_stream.cc" + "channels/method_channel_camera.cc" + "channels/method_channel_device.cc" "gst_camera.cc" "types/exposure_mode.cc" "types/focus_mode.cc" "types/orientation.cc" - "method_channel/method_channel_camera.cc" - "method_channel/method_channel_device.cc" ) apply_standard_settings(${PLUGIN_NAME}) set_target_properties(${PLUGIN_NAME} PROPERTIES diff --git a/packages/camera/elinux/camera_elinux_plugin.cc b/packages/camera/elinux/camera_elinux_plugin.cc index 8892b04..95b751c 100644 --- a/packages/camera/elinux/camera_elinux_plugin.cc +++ b/packages/camera/elinux/camera_elinux_plugin.cc @@ -11,11 +11,12 @@ #include #include "camera_stream_handler_impl.h" +#include "channels/event_channel_image_stream.h" +#include "channels/method_channel_camera.h" +#include "channels/method_channel_device.h" #include "events/camera_initialized_event.h" #include "gst_camera.h" #include "messages/messages.h" -#include "method_channel/method_channel_camera.h" -#include "method_channel/method_channel_device.h" namespace { constexpr char kCameraChannelName[] = "plugins.flutter.io/camera"; @@ -82,6 +83,12 @@ class CameraPlugin : public flutter::Plugin { void HandleInitializeCall( const flutter::EncodableValue* message, std::unique_ptr> result); + void HandleStartImageStreamCall( + const flutter::EncodableValue* message, + std::unique_ptr> result); + void HandleStopImageStreamCall( + const flutter::EncodableValue* message, + std::unique_ptr> result); void HandleGetMaxZoomLevelCall( const flutter::EncodableValue* message, std::unique_ptr> result); @@ -105,6 +112,9 @@ class CameraPlugin : public flutter::Plugin { std::unique_ptr texture_; std::unique_ptr camera_ = nullptr; int64_t texture_id_; + + std::unique_ptr event_channel_image_stream_ = + nullptr; std::unique_ptr method_channel_camera_; std::unique_ptr method_channel_device_; }; @@ -168,9 +178,9 @@ void CameraPlugin::HandleMethodCall( } else if (!method_name.compare(kCameraChannelApiSetFocusPoint)) { result->NotImplemented(); } else if (!method_name.compare(kCameraChannelApiStartImageStream)) { - result->NotImplemented(); + HandleStartImageStreamCall(method_call.arguments(), std::move(result)); } else if (!method_name.compare(kCameraChannelApiStopImageStream)) { - result->NotImplemented(); + HandleStopImageStreamCall(method_call.arguments(), std::move(result)); } else if (!method_name.compare(kCameraChannelApiGetMaxZoomLevel)) { HandleGetMaxZoomLevelCall(method_call.arguments(), std::move(result)); } else if (!method_name.compare(kCameraChannelApiGetMinZoomLevel)) { @@ -208,28 +218,30 @@ void CameraPlugin::HandleAvailableCamerasCall( void CameraPlugin::HandleCreateCall( const flutter::EncodableValue* message, std::unique_ptr> result) { - // auto meta = CreateMessage::FromMap(message); - buffer_ = std::make_unique(); texture_ = std::make_unique(flutter::PixelBufferTexture( - [host = this](size_t width, - size_t height) -> const FlutterDesktopPixelBuffer* { - host->buffer_->width = host->camera_->GetPreviewWidth(); - host->buffer_->height = host->camera_->GetPreviewHeight(); - host->buffer_->buffer = host->camera_->GetPreviewFrameBuffer(); - return host->buffer_.get(); + [this](size_t width, + size_t height) -> const FlutterDesktopPixelBuffer* { + buffer_->width = camera_->GetPreviewWidth(); + buffer_->height = camera_->GetPreviewHeight(); + buffer_->buffer = camera_->GetPreviewFrameBuffer(); + + // TODO: We need to handle this code (event_channel_image_stream_) + // in the proper place, but the Camera plugin doesn't have a main + // loop. + if (event_channel_image_stream_) { + event_channel_image_stream_->Send(buffer_->width, buffer_->height, + buffer_->buffer); + } + + return buffer_.get(); })); auto texture_id = texture_registrar_->RegisterTexture(texture_.get()); - auto stream_handler = std::make_unique( - // OnNotifyInitialized - []() {}, - // OnNotifyFrameDecoded - [texture_id, host = this]() { - host->texture_registrar_->MarkTextureFrameAvailable(texture_id); - }, - // OnNotifyCompleted - []() {}); + auto stream_handler = + std::make_unique([texture_id, this]() { + texture_registrar_->MarkTextureFrameAvailable(texture_id); + }); camera_ = std::make_unique(std::move(stream_handler)); texture_id_ = texture_id; @@ -273,6 +285,31 @@ void CameraPlugin::HandleInitializeCall( result->Success(); } +void CameraPlugin::HandleStartImageStreamCall( + const flutter::EncodableValue* message, + std::unique_ptr> result) { +// TODO: Support StartImageStream API. +#if 0 + event_channel_image_stream_ = + std::make_unique(plugin_registrar_); + result->Success(); +#else + result->NotImplemented(); +#endif +} + +void CameraPlugin::HandleStopImageStreamCall( + const flutter::EncodableValue* message, + std::unique_ptr> result) { +// TODO: Support StopImageStream API. +#if 0 + event_channel_image_stream_ = nullptr; + result->Success(); +#else + result->NotImplemented(); +#endif +} + void CameraPlugin::HandleGetMaxZoomLevelCall( const flutter::EncodableValue* message, std::unique_ptr> result) { diff --git a/packages/camera/elinux/camera_stream_handler.h b/packages/camera/elinux/camera_stream_handler.h index f7c828e..06f257b 100644 --- a/packages/camera/elinux/camera_stream_handler.h +++ b/packages/camera/elinux/camera_stream_handler.h @@ -14,19 +14,11 @@ class CameraStreamHandler { CameraStreamHandler(CameraStreamHandler const&) = delete; CameraStreamHandler& operator=(CameraStreamHandler const&) = delete; - // Notifies the completion of initializing the video player. - void OnNotifyInitialized() { OnNotifyInitializedInternal(); } - // Notifies the completion of decoding a video frame. void OnNotifyFrameDecoded() { OnNotifyFrameDecodedInternal(); } - // Notifies the completion of playing a video. - void OnNotifyCompleted() { OnNotifyCompletedInternal(); } - protected: - virtual void OnNotifyInitializedInternal() = 0; virtual void OnNotifyFrameDecodedInternal() = 0; - virtual void OnNotifyCompletedInternal() = 0; }; #endif // PACKAGES_CAMERA_CAMERA_ELINUX_CAMERA_STREAM_HANDLER_H_ diff --git a/packages/camera/elinux/camera_stream_handler_impl.h b/packages/camera/elinux/camera_stream_handler_impl.h index 55e5377..af69caf 100644 --- a/packages/camera/elinux/camera_stream_handler_impl.h +++ b/packages/camera/elinux/camera_stream_handler_impl.h @@ -11,16 +11,10 @@ class CameraStreamHandlerImpl : public CameraStreamHandler { public: - using OnNotifyInitialized = std::function; using OnNotifyFrameDecoded = std::function; - using OnNotifyCompleted = std::function; - CameraStreamHandlerImpl(OnNotifyInitialized on_notify_initialized, - OnNotifyFrameDecoded on_notify_frame_decoded, - OnNotifyCompleted on_notify_completed) - : on_notify_initialized_(on_notify_initialized), - on_notify_frame_decoded_(on_notify_frame_decoded), - on_notify_completed_(on_notify_completed) {} + CameraStreamHandlerImpl(OnNotifyFrameDecoded on_notify_frame_decoded) + : on_notify_frame_decoded_(on_notify_frame_decoded) {} virtual ~CameraStreamHandlerImpl() = default; // Prevent copying. @@ -28,13 +22,6 @@ class CameraStreamHandlerImpl : public CameraStreamHandler { CameraStreamHandlerImpl& operator=(CameraStreamHandlerImpl const&) = delete; protected: - // |CameraStreamHandler| - void OnNotifyInitializedInternal() { - if (on_notify_initialized_) { - on_notify_initialized_(); - } - } - // |CameraStreamHandler| void OnNotifyFrameDecodedInternal() { if (on_notify_frame_decoded_) { @@ -42,16 +29,7 @@ class CameraStreamHandlerImpl : public CameraStreamHandler { } } - // |CameraStreamHandler| - void OnNotifyCompletedInternal() { - if (on_notify_completed_) { - on_notify_completed_(); - } - } - - OnNotifyInitialized on_notify_initialized_; OnNotifyFrameDecoded on_notify_frame_decoded_; - OnNotifyCompleted on_notify_completed_; }; #endif // PACKAGES_CAMERA_CAMERA_ELINUX_CAMERA_STREAM_HANDLER_IMPL_H_ diff --git a/packages/camera/elinux/channels/event_channel_image_stream.cc b/packages/camera/elinux/channels/event_channel_image_stream.cc new file mode 100644 index 0000000..8aceaf4 --- /dev/null +++ b/packages/camera/elinux/channels/event_channel_image_stream.cc @@ -0,0 +1,72 @@ +// Copyright 2021 Sony Group Corporation. All rights reserved. +// 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. + +#include "channels/event_channel_image_stream.h" + +#include +#include + +#include + +namespace { +constexpr char kChannelName[] = "plugins.flutter.io/camera/imageStream"; + +// See: [getFormat()] in +// https://developer.android.com/reference/android/media/Image +constexpr int32_t kImageFormatRGBA8888 = 4; +}; // namespace + +EventChannelImageStream::EventChannelImageStream( + flutter::PluginRegistrar* registrar) { + auto event_channel = + std::make_unique>( + registrar->messenger(), kChannelName, + &flutter::StandardMethodCodec::GetInstance()); + + auto event_channel_handler = std::make_unique< + flutter::StreamHandlerFunctions>( + [this]( + const flutter::EncodableValue* arguments, + std::unique_ptr>&& events) + -> std::unique_ptr< + flutter::StreamHandlerError> { + event_sink_ = std::move(events); + return nullptr; + }, + [this](const flutter::EncodableValue* arguments) + -> std::unique_ptr< + flutter::StreamHandlerError> { + event_sink_ = nullptr; + return nullptr; + }); + event_channel->SetStreamHandler(std::move(event_channel_handler)); +} + +// See: [setImageStreamImageAvailableListener] in +// flutter/plugins/packages/camera/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java +void EventChannelImageStream::Send(const int32_t& width, const int32_t& height, + const uint8_t* pixels) { + const uint32_t len = width * 4 * height; + std::vector bytes(pixels, pixels + len); + + flutter::EncodableList planes; + flutter::EncodableMap plane = { + {flutter::EncodableValue("bytesPerRow"), flutter::EncodableValue(width)}, + {flutter::EncodableValue("bytesPerPixel"), flutter::EncodableValue(4)}, + {flutter::EncodableValue("bytes"), flutter::EncodableValue(bytes)}, + }; + flutter::EncodableValue plane_value(plane); + planes.push_back(plane_value); + + flutter::EncodableMap encodables = { + {flutter::EncodableValue("width"), flutter::EncodableValue(width)}, + {flutter::EncodableValue("height"), flutter::EncodableValue(height)}, + {flutter::EncodableValue("format"), + flutter::EncodableValue(kImageFormatRGBA8888)}, + {flutter::EncodableValue("planes"), flutter::EncodableValue(planes)}}; + flutter::EncodableValue event(encodables); + + event_sink_->Success(event); +} diff --git a/packages/camera/elinux/channels/event_channel_image_stream.h b/packages/camera/elinux/channels/event_channel_image_stream.h new file mode 100644 index 0000000..8e62a1e --- /dev/null +++ b/packages/camera/elinux/channels/event_channel_image_stream.h @@ -0,0 +1,27 @@ +// Copyright 2021 Sony Group Corporation. All rights reserved. +// 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. + +#ifndef PACKAGES_CAMERA_CAMERA_ELINUX_CAMERA_CHANNELS_EVENT_CHANNEL_IMAGE_STREAM_H_ +#define PACKAGES_CAMERA_CAMERA_ELINUX_CAMERA_CHANNELS_EVENT_CHANNEL_IMAGE_STREAM_H_ + +#include +#include +#include + +#include + +class EventChannelImageStream { + public: + EventChannelImageStream(flutter::PluginRegistrar* registrar); + ~EventChannelImageStream() = default; + + void Send(const int32_t& width, const int32_t& height, const uint8_t* pixels); + + private: + std::unique_ptr> channel_; + std::unique_ptr> event_sink_; +}; + +#endif // PACKAGES_CAMERA_CAMERA_ELINUX_CAMERA_CHANNELS_EVENT_CHANNEL_IMAGE_STREAM_H_ diff --git a/packages/camera/elinux/method_channel/method_channel_camera.cc b/packages/camera/elinux/channels/method_channel_camera.cc similarity index 96% rename from packages/camera/elinux/method_channel/method_channel_camera.cc rename to packages/camera/elinux/channels/method_channel_camera.cc index 36e0a50..5f284d1 100644 --- a/packages/camera/elinux/method_channel/method_channel_camera.cc +++ b/packages/camera/elinux/channels/method_channel_camera.cc @@ -3,7 +3,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "method_channel/method_channel_camera.h" +#include "channels/method_channel_camera.h" #include diff --git a/packages/camera/elinux/method_channel/method_channel_camera.h b/packages/camera/elinux/channels/method_channel_camera.h similarity index 70% rename from packages/camera/elinux/method_channel/method_channel_camera.h rename to packages/camera/elinux/channels/method_channel_camera.h index cb5854a..9078f85 100644 --- a/packages/camera/elinux/method_channel/method_channel_camera.h +++ b/packages/camera/elinux/channels/method_channel_camera.h @@ -3,8 +3,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef PACKAGES_CAMERA_CAMERA_ELINUX_CAMERA_METHOD_CHANNEL_METHOD_CHANNEL_CAMERA_H_ -#define PACKAGES_CAMERA_CAMERA_ELINUX_CAMERA_METHOD_CHANNEL_METHOD_CHANNEL_CAMERA_H_ +#ifndef PACKAGES_CAMERA_CAMERA_ELINUX_CAMERA_CHANNELS_METHOD_CHANNEL_CAMERA_H_ +#define PACKAGES_CAMERA_CAMERA_ELINUX_CAMERA_CHANNELS_METHOD_CHANNEL_CAMERA_H_ #include #include @@ -14,12 +14,6 @@ #include "events/camera_initialized_event.h" -enum class CameraEventType { - kError, - kCameraClosing, - kInitialized, -}; - class MethodChannelCamera { public: MethodChannelCamera(flutter::PluginRegistrar* registrar, int64_t camera_id); @@ -34,4 +28,4 @@ class MethodChannelCamera { std::unique_ptr> channel_; }; -#endif // PACKAGES_CAMERA_CAMERA_ELINUX_CAMERA_METHOD_CHANNEL_METHOD_CHANNEL_CAMERA_H_ +#endif // PACKAGES_CAMERA_CAMERA_ELINUX_CAMERA_CHANNELS_METHOD_CHANNEL_CAMERA_H_ diff --git a/packages/camera/elinux/method_channel/method_channel_device.cc b/packages/camera/elinux/channels/method_channel_device.cc similarity index 96% rename from packages/camera/elinux/method_channel/method_channel_device.cc rename to packages/camera/elinux/channels/method_channel_device.cc index 8dbc0a9..be12694 100644 --- a/packages/camera/elinux/method_channel/method_channel_device.cc +++ b/packages/camera/elinux/channels/method_channel_device.cc @@ -3,7 +3,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "method_channel/method_channel_device.h" +#include "channels/method_channel_device.h" #include diff --git a/packages/camera/elinux/method_channel/method_channel_device.h b/packages/camera/elinux/channels/method_channel_device.h similarity index 75% rename from packages/camera/elinux/method_channel/method_channel_device.h rename to packages/camera/elinux/channels/method_channel_device.h index 02533fd..a22f9ad 100644 --- a/packages/camera/elinux/method_channel/method_channel_device.h +++ b/packages/camera/elinux/channels/method_channel_device.h @@ -3,8 +3,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef PACKAGES_CAMERA_CAMERA_ELINUX_CAMERA_METHOD_CHANNEL_METHOD_CHANNEL_DEVICE_H_ -#define PACKAGES_CAMERA_CAMERA_ELINUX_CAMERA_METHOD_CHANNEL_METHOD_CHANNEL_DEVICE_H_ +#ifndef PACKAGES_CAMERA_CAMERA_ELINUX_CAMERA_CHANNELS_METHOD_CHANNEL_DEVICE_H_ +#define PACKAGES_CAMERA_CAMERA_ELINUX_CAMERA_CHANNELS_METHOD_CHANNEL_DEVICE_H_ #include #include @@ -28,4 +28,4 @@ class MethodChannelDevice { std::unique_ptr> channel_; }; -#endif // PACKAGES_CAMERA_CAMERA_ELINUX_CAMERA_METHOD_CHANNEL_METHOD_CHANNEL_DEVICE_H_ +#endif // PACKAGES_CAMERA_CAMERA_ELINUX_CAMERA_CHANNELS_METHOD_CHANNEL_DEVICE_H_