| // Copyright 2019 The Fuchsia 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 SRC_CAMERA_DRIVERS_CONTROLLER_PIPELINE_MANAGER_H_ |
| #define SRC_CAMERA_DRIVERS_CONTROLLER_PIPELINE_MANAGER_H_ |
| |
| #include <fuchsia/camera2/cpp/fidl.h> |
| #include <lib/async/cpp/wait.h> |
| |
| #include <unordered_map> |
| #include <vector> |
| |
| #include "src/camera/drivers/controller/configs/internal_config.h" |
| #include "src/camera/drivers/controller/memory_allocation.h" |
| #include "src/camera/drivers/controller/output_node.h" |
| #include "src/camera/drivers/controller/stream_pipeline_info.h" |
| |
| namespace camera { |
| |
| namespace { |
| constexpr auto kPipelineManagerSignalExitDone = ZX_USER_SIGNAL_0; |
| constexpr auto kTaskQueued = ZX_USER_SIGNAL_0; |
| } // namespace |
| |
| // |PipelineManager| |
| // This class provides a way to create the stream pipeline for a particular |
| // stream configuration requested. |
| // While doing so it would also create ISP stream protocol and client stream protocols |
| // and setup the camera pipeline such that the streams are flowing properly as per the |
| // requested stream configuration. |
| class PipelineManager { |
| public: |
| PipelineManager(zx_device_t* device, async_dispatcher_t* dispatcher, |
| const ddk::IspProtocolClient& isp, const ddk::GdcProtocolClient& gdc, |
| const ddk::Ge2dProtocolClient& ge2d, |
| fuchsia::sysmem::AllocatorSyncPtr sysmem_allocator, |
| const zx::event& shutdown_event) |
| : shutdown_event_(shutdown_event), |
| device_(device), |
| dispatcher_(dispatcher), |
| isp_(isp), |
| gdc_(gdc), |
| ge2d_(ge2d), |
| memory_allocator_(std::move(sysmem_allocator)) { |
| SetupTaskWaiter(); |
| } |
| |
| void ConfigureStreamPipeline(StreamCreationData info, |
| fidl::InterfaceRequest<fuchsia::camera2::Stream> stream); |
| |
| // Disconnects the stream. |
| // This is called when the stream channel receives a ZX_ERR_PEER_CLOSE message. |
| // |stream_to_be_disconnected| : Stream type of the stream to be disconnected. |
| void OnClientStreamDisconnect(fuchsia::camera2::CameraStreamType stream_to_be_disconnected); |
| |
| ProcessNode* full_resolution_stream() const { |
| return FindStream(fuchsia::camera2::CameraStreamType::FULL_RESOLUTION); |
| } |
| |
| ProcessNode* downscaled_resolution_stream() const { |
| return FindStream(fuchsia::camera2::CameraStreamType::DOWNSCALED_RESOLUTION); |
| } |
| |
| void StopStreaming(); |
| void StartStreaming(); |
| |
| // Shuts down all existing streams |
| void Shutdown(); |
| |
| // Finds which graph head is the requested stream |stream_type| configured in. |
| fit::result<std::pair<ProcessNode*, fuchsia::camera2::CameraStreamType>, zx_status_t> |
| FindGraphHead(fuchsia::camera2::CameraStreamType stream_type); |
| |
| private: |
| // Creates an async wait object which waits on |tasks_event_| to check the task queue and drains |
| // it. |
| void SetupTaskWaiter(); |
| |
| // Posts a task on the task queue. All the tasks related to the manipulation of the stream |
| // configurations need to be posted on the task queue instead of directly posting them on the loop |
| // using async::PostTask(). Note: The task posted to the queue needs to call TaskComplete() to |
| // signal completion of the task. |
| void PostTask(fit::closure task); |
| |
| // Signals the completion of the task. |
| void TaskComplete(); |
| |
| // Frees up the nodes after the stream pipeline has been shutdown |
| // when |stream_to_disconnect| stream is disconnected. |
| // After a stream has shutdown, we have to check again to see what part of the |
| // graph needs to be freed up because there is a possibility where while a portion |
| // of graph is waiting to be shut down, another request for disconnection came in for |
| // same |input_stream_type|. |
| void DeleteGraphForDisconnectedStream(ProcessNode* graph_head, |
| fuchsia::camera2::CameraStreamType stream_to_disconnect); |
| |
| // Creates the stream pipeline graph and appends it to the input node (|parent_node|). |
| // Args: |
| // |internal_node| : Internal node of the node where this new graph needs to append. |
| // |parent_node| : Pointer to the node to which we need to append this new graph. |
| // Returns: |
| // |OutputNode*| : Pointer to the ouput node. |
| fit::result<OutputNode*, zx_status_t> CreateGraph(StreamCreationData* info, |
| const InternalConfigNode& internal_node, |
| ProcessNode* parent_node); |
| |
| fit::result<std::pair<InternalConfigNode, ProcessNode*>, zx_status_t> FindNodeToAttachNewStream( |
| StreamCreationData* info, const InternalConfigNode& current_internal_node, |
| ProcessNode* graph_head); |
| |
| // Helper function to find out which portion of the graph |
| // needs to be disconnected and shut down. |
| void DisconnectStream(ProcessNode* graph_head, |
| fuchsia::camera2::CameraStreamType input_stream_type, |
| fuchsia::camera2::CameraStreamType stream_to_disconnect); |
| |
| ProcessNode* FindStream(fuchsia::camera2::CameraStreamType stream) const { |
| auto stream_entry = streams_.find(stream); |
| if (stream_entry != streams_.end()) { |
| return stream_entry->second.get(); |
| } |
| return nullptr; |
| } |
| |
| bool global_shutdown_requested_ = false; |
| const zx::event& shutdown_event_; |
| zx_device_t* device_; |
| async_dispatcher_t* dispatcher_; |
| ddk::IspProtocolClient isp_; |
| ddk::GdcProtocolClient gdc_; |
| ddk::Ge2dProtocolClient ge2d_; |
| ControllerMemoryAllocator memory_allocator_; |
| // Map of Input streams -> ProcessNodes |
| std::unordered_map<fuchsia::camera2::CameraStreamType, std::unique_ptr<ProcessNode>> streams_; |
| // Map of Output streams -> OutputNodes |
| std::unordered_map<fuchsia::camera2::CameraStreamType, OutputNode*> output_nodes_info_; |
| std::vector<fuchsia::camera2::CameraStreamType> stream_shutdown_requested_; |
| // Queue for stream creation & deletion tasks. |
| std::queue<fit::closure> task_queue_; |
| bool task_in_progress_ = false; |
| zx::event tasks_event_; |
| async::Wait tasks_event_waiter_; |
| }; |
| |
| } // namespace camera |
| |
| #endif // SRC_CAMERA_DRIVERS_CONTROLLER_PIPELINE_MANAGER_H_ |