blob: 325a17ee51fc9cd2dd77caed74a97071e1da9e88 [file] [log] [blame]
// Copyright 2018 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 GARNET_LIB_MEDIA_CAMERA_SIMPLE_CAMERA_LIB_CAMERA_CLIENT_H_
#define GARNET_LIB_MEDIA_CAMERA_SIMPLE_CAMERA_LIB_CAMERA_CLIENT_H_
#include <vector>
#include <fbl/auto_lock.h>
#include <fbl/mutex.h>
#include <fbl/vector.h>
#include <garnet/lib/media/camera/simple_camera_lib/camera_interface_base.h>
#include <lib/async/cpp/wait.h>
#include <lib/fxl/files/unique_fd.h>
#include <lib/fxl/logging.h>
#include <zircon/device/camera-proto.h>
#include <zircon/device/camera.h>
#include <zircon/types.h>
#include <zx/channel.h>
#include <zx/vmo.h>
namespace simple_camera {
// The method for setting up a camera stream is as follows:
// 1) client.Open(device_id)
// 2) client.GetSupportedFormats
// 3) --> Receive GetSupportedFormats callback with formats
// 4) client.SetFormat(The format you select)
// 5) --> Receive SetFormat callback with maximum frame size
// 6) SetBuffer(vmo you allocate)
// 6.5) --> Receive SetBuffer callback (optional, since CameraClient will
// serialize the SetBuffer and start commands
// 7) Start
// ----------------------
// Normal operation:
// ---> Receive FrameNotifyCallback when a frame is available
// Consume the frame
// client.ReleaseFrame
// CameraClient is not generally thread safe.
// CameraClient does have some thread safe properties, assuming that:
// 1) There is only one thread handling the channel messages
// 2) There is only one thread calling the public interface functions
class CameraClient : public CameraInterfaceBase {
public:
CameraClient();
virtual ~CameraClient();
// Get the supported formats for the camera.
// get_formats_callback will be called in response.
zx_status_t GetSupportedFormats(GetFormatCallback get_formats_callback);
// Set the format of the video stream. This function
// should only be called once in the setup of the stream.
zx_status_t SetFormat(const camera_video_format_t& format,
SetFormatCallback set_format_callback);
// Set the vmo that will be used to pass video information from the driver
// to the consumer. The entire vmo is assumed to be available. The driver
// will provide the offset into the vmo at which a frame has been written.
// This function should only be called once in the setup of the stream.
zx_status_t SetBuffer(const zx::vmo& vmo);
// Signal the driver to start producing frames. Upon each frame being
// written, |frame_notify_callback| will be called. Start can be called
// immediatly after calling SetBuffer.
// This function should only be called once in the setup of the stream.
zx_status_t Start(FrameNotifyCallback frame_notify_callback);
// Release the lock on a video frame. The data_offset corresponds to the
// data_vb_offset field given in the camera_vb_frame_notify_t passed to
// the frame_notify_callback.
zx_status_t ReleaseFrame(uint64_t data_offset);
// Signal the driver that it should stop producing frames.
// Frame notifications may occur after calling this function.
zx_status_t Stop();
// Open Functions:
// shutdown_callback will be called when this class disconnects from the
// device, unless Close() is called, or this class is destructed.
// The callback will be called from the async waiter thread.
// Open a device in /dev/class/camera/ with the ID of dev_id.
zx_status_t Open(uint32_t dev_id, OnShutdownCallback shutdown_callback);
// Open a device in by folder decriptor and filename.
zx_status_t Open(int dir_fd, const std::string& name,
OnShutdownCallback shutdown_callback);
// Shuts down the interface, by dropping all connections.
// It is assumed that the driver will do the right thing when its
// channel closes.
// Close does not call the OnShutdownCallback passed into Open. It is only
// used as a library call, in the destructor, and when things fail in the
// Open call.
void Close();
private:
// The callbacks functions which get called upon incoming messages over the
// channel:
zx_status_t OnGetFormatsResp(camera::camera_proto::GetFormatsResp resp);
zx_status_t OnSetFormatResp(camera::camera_proto::SetFormatResp resp,
zx::channel ch);
zx_status_t OnFrameNotify(camera::camera_proto::VideoBufFrameNotify resp);
// Called when a new message is received on the Command channel:
void OnNewCmdMessage(async_t* async,
async::WaitBase* wait,
zx_status_t status,
const zx_packet_signal* signal);
zx_status_t ProcessCmdChannel();
// Called when a new message is received on the Streaming channel:
void OnNewBufferMessage(async_t* async,
async::WaitBase* wait,
zx_status_t status,
const zx_packet_signal* signal);
zx_status_t ProcessBufferChannel();
// Opens the channel to the device
zx_status_t OpenChannel(fxl::UniqueFD dev_node,
OnShutdownCallback shutdown_callback);
// Send the stop command to the driver. This differs from the public Stop()
// which deals with the state of the driver.
zx_status_t SendStop();
// Internal Shutdown. Closes everything and notifies the calling application
// that it is shutting down.
void CloseAndNotify();
enum CameraState : uint16_t {
Closed = 0x0000,
Error = 0x0100,
Configuring = 0x0200,
// All the states we step through during configuration:
CommandChannelOpen = 0x0201,
FormatsRequested = 0x0203,
FormatsReceived = 0x0205,
SetFormatRequested = 0x0207,
SetFormatReceived = 0x0211,
BufferChannelOpen = 0x0210,
SetBufferRequested = 0x0231,
StartRequested = 0x0251,
ChannelsMask = 0x0011,
Streaming = 0x0400,
};
// --------- State Machine Functions ---------------
// All the state machine functions are guarded by the state_lock_ mutex.
// This allows us to ensure atomic state transitions.
// Verify that we are in a given state:
zx_status_t CheckConfigurationState(CameraState required_state);
// Set the next state. This first checks that we are in the current_state,
// so we can detect (if called in a multithreaded fashion) if a state had
// changed during the call.
void SetConfigurationState(CameraState current_state, CameraState next_state);
// Check the various main states:
bool IsStreaming();
bool IsConfiguring();
bool IsClosed();
void SetStreaming();
// Callbacks for asyncronous operations.
// These functions are also used to determine state; if they are defined,
// then we are waiting for the appropriate response
SetFormatCallback set_format_callback_ = nullptr;
GetFormatCallback get_formats_callback_ = nullptr;
FrameNotifyCallback frame_notify_callback_ = nullptr;
OnShutdownCallback client_shutdown_notifier_ = nullptr;
CameraState state_ __TA_GUARDED(state_lock_) = CameraState::Closed;
fbl::Mutex state_lock_;
zx::channel stream_ch_;
zx::channel vb_ch_;
std::vector<camera_video_format_t> out_formats_;
async::WaitMethod<CameraClient, &CameraClient::OnNewCmdMessage>
cmd_msg_waiter_{this};
async::WaitMethod<CameraClient, &CameraClient::OnNewBufferMessage>
buff_msg_waiter_{this};
};
} // namespace simple_camera
#endif // GARNET_LIB_MEDIA_CAMERA_SIMPLE_CAMERA_LIB_CAMERA_CLIENT_H_