// 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_INPUT_NODE_H_
#define SRC_CAMERA_DRIVERS_CONTROLLER_INPUT_NODE_H_

#include <fuchsia/camera2/cpp/fidl.h>
#include <lib/trace/event.h>
#include <zircon/assert.h>

#include <ddktl/protocol/isp.h>

#include "src/camera/drivers/controller/isp_stream_protocol.h"
#include "src/camera/drivers/controller/memory_allocation.h"
#include "src/camera/drivers/controller/processing_node.h"
#include "src/camera/drivers/controller/stream_pipeline_info.h"

// |InputNode| represents a |ProcessNode| which would talk to the
// ISP driver.
namespace camera {

class InputNode : public ProcessNode {
 public:
  InputNode(StreamCreationData* info,
            fuchsia::sysmem::BufferCollectionInfo_2 output_buffer_collection,
            async_dispatcher_t* dispatcher, const ddk::IspProtocolClient& isp)
      : ProcessNode(NodeType::kInputStream, nullptr, info->stream_type(), info->node.image_formats,
                    std::move(output_buffer_collection), info->node.supported_streams, dispatcher,
                    info->node.output_frame_rate, info->image_format_index),
        isp_stream_type_(info->node.input_stream_type),
        isp_frame_callback_{OnIspFrameAvailable, this},
        isp_(isp) {}

  // Creates an |InputNode| object.
  // 1. Creates the ISP stream protocol
  // 2. Creates the requested ISP stream
  // 3. Allocates buffers if needed
  // Args:
  // |info| : StreamCreationData for the requested stream.
  // |memory_allocator| : Memory allocator object to allocate memory using sysmem.
  // |dispatcher| : Dispatcher on which GDC tasks can be queued up.
  // |isp| : ISP protocol to talk to the driver.
  static fit::result<std::unique_ptr<InputNode>, zx_status_t> CreateInputNode(
      StreamCreationData* info, const ControllerMemoryAllocator& memory_allocator,
      async_dispatcher_t* dispatcher, const ddk::IspProtocolClient& isp);

  const hw_accel_frame_callback_t* isp_frame_callback() { return &isp_frame_callback_; }

  std::unique_ptr<camera::IspStreamProtocol>& isp_stream_protocol() { return isp_stream_protocol_; }

  void set_isp_stream_protocol(std::unique_ptr<camera::IspStreamProtocol> isp_stream_protocol) {
    isp_stream_protocol_ = std::move(isp_stream_protocol);
  }

  // Notifies that a frame is ready to be sent to the client.
  void OnReadyToProcess(const frame_available_info_t* info) override;

  // Releases the frame associated with | buffer_index |.
  void OnReleaseFrame(uint32_t buffer_index) override;

  // Notifies that a frame is done processing by this node.
  void OnFrameAvailable(const frame_available_info_t* info) override;

  // Shuts down the stream with ISP.
  void OnShutdown(fit::function<void(void)> shutdown_callback) override;

  // Notifies that the client has requested to start streaming.
  void OnStartStreaming() override;

  // Notifies that the client has requested to stop streaming.
  void OnStopStreaming() override;

  // Notifies that the client has requested to change resolution.
  void OnResolutionChangeRequest(uint32_t output_format_index) override {}

 private:
  // Notifies when a new frame is available from the ISP.
  static void OnIspFrameAvailable(void* ctx, const frame_available_info_t* info) {
    auto nonce = TRACE_NONCE();
    TRACE_DURATION("camera", "OnIspFrameAvailable");
    TRACE_FLOW_BEGIN("camera", "post_ready_to_process", nonce);
    // This method is invoked by the ISP in its own thread,
    // so the event must be marshalled to the
    // controller's thread.
    auto* input_node = static_cast<InputNode*>(ctx);
    input_node->RunOnMainThread([input_node, nonce, info = *info]() {
      TRACE_DURATION("camera", "OnIspFrameAvailable.task");
      TRACE_FLOW_END("camera", "post_ready_to_process", nonce);
      input_node->OnReadyToProcess(&info);
    });
  }

  // ISP stream type.
  __UNUSED fuchsia::camera2::CameraStreamType isp_stream_type_;
  // ISP Frame callback.
  hw_accel_frame_callback_t isp_frame_callback_;
  // ISP stream protocol.
  std::unique_ptr<IspStreamProtocol> isp_stream_protocol_;
  // Protocol to talk to ISP driver.
  ddk::IspProtocolClient isp_;
};

}  // namespace camera

#endif  // SRC_CAMERA_DRIVERS_CONTROLLER_INPUT_NODE_H_
