blob: a1cbd58be33ce414dec8de73d044d8e913c6ed16 [file] [log] [blame]
// 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_PROCESSING_NODE_H_
#define SRC_CAMERA_DRIVERS_CONTROLLER_PROCESSING_NODE_H_
#include <fuchsia/camera2/cpp/fidl.h>
#include <fuchsia/hardware/gdc/cpp/banjo.h>
#include <fuchsia/hardware/isp/cpp/banjo.h>
#include <lib/async/cpp/task.h>
#include <lib/fit/thread_checker.h>
#include <zircon/assert.h>
#include <queue>
#include <vector>
#include <fbl/auto_lock.h>
#include <fbl/macros.h>
#include "src/camera/drivers/controller/configs/internal_config.h"
namespace camera {
class ProcessNode;
class StreamImpl;
class ProcessNode {
public:
DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ProcessNode);
ProcessNode(NodeType type, ProcessNode* parent_node,
fuchsia::camera2::CameraStreamType current_stream_type,
const std::vector<fuchsia::sysmem::ImageFormat_2>& output_image_formats,
fuchsia::sysmem::BufferCollectionInfo_2 output_buffer_collection,
const std::vector<StreamInfo>& supported_streams, async_dispatcher_t* dispatcher,
fuchsia::camera2::FrameRate frame_rate, uint32_t current_image_format_index)
: dispatcher_(dispatcher),
output_frame_rate_(frame_rate),
type_(type),
parent_node_(parent_node),
output_buffer_collection_(std::move(output_buffer_collection)),
output_image_formats_(output_image_formats),
enabled_(false),
supported_streams_(supported_streams),
in_use_buffer_count_(output_buffer_collection.buffer_count, 0),
current_image_format_index_(current_image_format_index) {
configured_streams_.push_back(current_stream_type);
}
virtual ~ProcessNode() {
// We need to ensure that the child nodes
// are destructed before parent node.
child_nodes_.clear();
}
// Notifies that a frame is ready for processing at this node.
virtual void OnReadyToProcess(const frame_available_info_t* info) = 0;
// Notifies that a frame is released.
virtual void OnReleaseFrame(uint32_t buffer_index) = 0;
// Notifies that the client has requested to start streaming.
virtual void OnStartStreaming();
// Notifies that the client has requested to stop streaming.
virtual void OnStopStreaming();
// Shut down routine.
virtual void OnShutdown(fit::function<void(void)> shutdown_callback) = 0;
// Notifies that the client has requested to change resolution.
virtual void OnResolutionChangeRequest(uint32_t output_format_index) = 0;
// Notifies that the client has requested a new crop rectangle.
virtual zx_status_t OnSetCropRect(float /*x_min*/, float /*y_min*/, float /*x_max*/,
float /*y_max*/) {
return ZX_ERR_NOT_SUPPORTED;
}
// Notifies that the resolution has been changed.
void OnResolutionChanged(const frame_available_info* info);
void RunOnMainThread(fit::closure handler) { async::PostTask(dispatcher_, std::move(handler)); }
void set_enabled(bool enabled) { enabled_ = enabled; }
// Updates the frame counter for all child nodes.
void UpdateFrameCounterForAllChildren();
// Decides if we need to drop the frame.
bool NeedToDropFrame();
NodeType type() { return type_; }
std::vector<fuchsia::sysmem::ImageFormat_2>& output_image_formats() {
return output_image_formats_;
}
fuchsia::sysmem::BufferCollectionInfo_2& output_buffer_collection() {
return output_buffer_collection_;
}
uint32_t current_image_format_index() const { return current_image_format_index_; }
ProcessNode* parent_node() { return parent_node_; }
uint32_t output_fps() const {
ZX_ASSERT_MSG(output_frame_rate_.frames_per_sec_numerator %
output_frame_rate_.frames_per_sec_denominator ==
0,
"Unsupported Frame Rate");
return output_frame_rate_.frames_per_sec_numerator /
output_frame_rate_.frames_per_sec_denominator;
}
std::vector<fuchsia::camera2::CameraStreamType>& configured_streams() {
return configured_streams_;
}
// For tests.
uint32_t get_in_use_buffer_count(uint32_t buffer_index) {
{
fbl::AutoLock al(&in_use_buffer_lock_);
ZX_ASSERT(buffer_index < in_use_buffer_count_.size());
return in_use_buffer_count_[buffer_index];
}
}
bool is_stream_supported(fuchsia::camera2::CameraStreamType stream) {
return std::any_of(
supported_streams_.begin(), supported_streams_.end(),
[stream](auto& supported_stream) { return supported_stream.type == stream; });
}
bool is_dynamic_resolution_supported(fuchsia::camera2::CameraStreamType stream) {
for (auto& supported_stream : supported_streams_) {
if (supported_stream.type == stream) {
return supported_stream.supports_dynamic_resolution;
}
}
return false;
}
bool is_crop_region_supported(fuchsia::camera2::CameraStreamType stream) {
for (auto& supported_stream : supported_streams_) {
if (supported_stream.type == stream) {
return supported_stream.supports_crop_region;
}
}
return false;
}
const std::vector<StreamInfo>& supported_streams() { return supported_streams_; }
std::vector<std::unique_ptr<ProcessNode>>& child_nodes() { return child_nodes_; }
// Adds a child node in the vector.
void AddChildNodeInfo(std::unique_ptr<ProcessNode> child_node) {
child_nodes_.push_back(std::move(child_node));
}
void set_current_image_format_index(uint32_t index) { current_image_format_index_ = index; }
// Curent state of the node.
bool enabled() const { return enabled_; }
uint32_t current_frame_count() const { return current_frame_count_; }
void AddToCurrentFrameCount(uint32_t frame_count) { current_frame_count_ += frame_count; }
void SubtractFromCurrentFrameCount(uint32_t frame_count) { current_frame_count_ -= frame_count; }
async_dispatcher_t* dispatcher() const { return dispatcher_; }
protected:
bool AllChildNodesDisabled();
void OnCallbackReceived() {
if (node_callback_received_ && child_node_callback_received_) {
shutdown_callback_();
}
}
// Notifies that a frame is done processing by this node.
virtual void OnFrameAvailable(const frame_available_info_t* info);
// Dispatcher for the frame processng loop.
async_dispatcher_t* dispatcher_;
// Lock to guard |in_use_buffer_count_|
fbl::Mutex in_use_buffer_lock_;
// The output frame rate for this node.
fuchsia::camera2::FrameRate output_frame_rate_;
// Current frame counter. This is in terms of no. of output frames
// worth of input recieved.
// current_frame_count = (no. of input frames generated * output_frame_rate)
uint32_t current_frame_count_ = 0;
// Type of node.
NodeType type_;
// List of all the children for this node.
std::vector<std::unique_ptr<ProcessNode>> child_nodes_;
// Parent node.
ProcessNode* const parent_node_;
fuchsia::sysmem::BufferCollectionInfo_2 output_buffer_collection_;
// Ouput Image formats.
// These are needed when we initialize HW accelerators.
std::vector<fuchsia::sysmem::ImageFormat_2> output_image_formats_;
bool enabled_;
// The Stream types this node already supports and configured.
std::vector<fuchsia::camera2::CameraStreamType> configured_streams_;
// The Stream types this node could support as well.
std::vector<StreamInfo> supported_streams_;
// A vector to keep track of outstanding in-use buffers handed off to all child nodes.
// [buffer_index] --> [count]
std::vector<uint32_t> in_use_buffer_count_ __TA_GUARDED(in_use_buffer_lock_);
// ISP/GDC or GE2D shutdown complete status.
bool node_callback_received_ = false;
// Child node shutdown complete status.
bool child_node_callback_received_ = false;
fit::function<void(void)> shutdown_callback_;
bool shutdown_requested_ = false;
uint32_t current_image_format_index_;
fit::thread_checker thread_checker_;
};
} // namespace camera
#endif // SRC_CAMERA_DRIVERS_CONTROLLER_PROCESSING_NODE_H_