blob: bd57d4b11e5788a5922e9198339cd1ef76b46858 [file] [log] [blame]
/* Copyright 2016 The Chromium OS 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 HAL_USB_CAMERA_CLIENT_H_
#define HAL_USB_CAMERA_CLIENT_H_
#include <memory>
#include <queue>
#include <string>
#include <vector>
#include <base/bind.h>
#include <base/macros.h>
#include <base/synchronization/lock.h>
#include <base/threading/thread.h>
#include <base/threading/thread_checker.h>
#include <camera/camera_metadata.h>
#include <hardware/camera3.h>
#include <hardware/hardware.h>
#include "cros-camera/camera_buffer_manager.h"
#include "cros-camera/future.h"
#include "hal/usb/cached_frame.h"
#include "hal/usb/capture_request.h"
#include "hal/usb/common_types.h"
#include "hal/usb/frame_buffer.h"
#include "hal/usb/metadata_handler.h"
#include "hal/usb/test_pattern.h"
#include "hal/usb/v4l2_camera_device.h"
namespace cros {
// CameraClient class is not thread-safe. There are three threads in this
// class.
// 1. Hal thread: Called from hal adapter. Constructor and OpenDevice are called
// on hal thread.
// 2. Device ops thread: Called from hal adapter. Camera v3 Device Operations
// (except dump) run on this thread. CloseDevice also runs on this thread.
// 3. Request thread: Owned by this class. Used to handle all requests. The
// functions in RequestHandler run on request thread.
//
// Android framework synchronizes Constructor, OpenDevice, CloseDevice, and
// device ops. The following items are guaranteed by Android frameworks. Note
// that HAL adapter has more restrictions that all functions of device ops
// (except dump) run on the same thread.
// 1. Open, Initialize, and Close are not concurrent with any of the method in
// device ops.
// 2. Dump can be called at any time.
// 3. ConfigureStreams is not concurrent with either ProcessCaptureRequest or
// Flush.
// 4. Flush can be called concurrently with ProcessCaptureRequest.
// 5. ConstructDefaultRequestSettings may be called concurrently to any of the
// device ops.
class CameraClient {
public:
// id is used to distinguish cameras. 0 <= id < number of cameras.
CameraClient(int id,
const DeviceInfo& device_info,
const camera_metadata_t& static_info,
const hw_module_t* module,
hw_device_t** hw_device);
~CameraClient();
// Camera Device Operations from CameraHal.
int OpenDevice();
int CloseDevice();
int GetId() const { return id_; }
// Camera v3 Device Operations (see <hardware/camera3.h>)
int Initialize(const camera3_callback_ops_t* callback_ops);
int ConfigureStreams(camera3_stream_configuration_t* stream_list);
// |type| is camera3_request_template_t in camera3.h.
const camera_metadata_t* ConstructDefaultRequestSettings(int type);
int ProcessCaptureRequest(camera3_capture_request_t* request);
void Dump(int fd);
int Flush(const camera3_device_t* dev);
private:
// Verify a set of streams in aggregate.
bool IsValidStreamSet(const std::vector<camera3_stream_t*>& streams);
// Calculate usage and maximum number of buffers of each stream.
void SetUpStreams(int num_buffers, std::vector<camera3_stream_t*>* streams);
// Start |request_thread_| and streaming.
int StreamOn(Size stream_on_resolution,
bool constant_frame_rate,
int crop_rotate_scale_degrees,
int* num_buffers);
// Stop streaming and |request_thread_|.
void StreamOff();
// Callback function for RequestHandler::StreamOn.
void StreamOnCallback(scoped_refptr<cros::Future<int>> future,
int* out_num_buffers,
int num_buffers,
int result);
// Callback function for RequestHandler::StreamOff.
void StreamOffCallback(scoped_refptr<cros::Future<int>> future, int result);
// Camera device id.
const int id_;
// Camera device information.
const DeviceInfo device_info_;
// Delegate to communicate with camera device.
std::unique_ptr<V4L2CameraDevice> device_;
// Camera device handle returned to framework for use.
camera3_device_t camera3_device_;
// Use to check the constructor, OpenDevice, and CloseDevice are called on the
// same thread.
base::ThreadChecker thread_checker_;
// Use to check camera v3 device operations are called on the same thread.
base::ThreadChecker ops_thread_checker_;
// Methods used to call back into the framework.
const camera3_callback_ops_t* callback_ops_;
// Handle metadata events and store states.
std::unique_ptr<MetadataHandler> metadata_handler_;
// Metadata for latest request.
android::CameraMetadata latest_request_metadata_;
// The formats used to report to apps.
SupportedFormats qualified_formats_;
// RequestHandler is used to handle in-flight requests. All functions in the
// class run on |request_thread_|. The class will be created in StreamOn and
// destroyed in StreamOff.
class RequestHandler {
public:
RequestHandler(
const int device_id,
const DeviceInfo& device_info,
V4L2CameraDevice* device,
const camera3_callback_ops_t* callback_ops,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
MetadataHandler* metadata_handler);
~RequestHandler();
// Synchronous call to start streaming.
void StreamOn(Size stream_on_resolution,
bool constant_frame_rate,
int crop_rotate_scale_degrees,
const base::Callback<void(int, int)>& callback);
// Synchronous call to stop streaming.
void StreamOff(const base::Callback<void(int)>& callback);
// Handle one request.
void HandleRequest(std::unique_ptr<CaptureRequest> request);
// Handle flush request. This function can be called on any thread.
void HandleFlush(const base::Callback<void(int)>& callback);
private:
// Start streaming implementation.
int StreamOnImpl(Size stream_on_resolution, bool constant_frame_rate);
// Stop streaming implementation.
int StreamOffImpl();
// Handle aborted request when flush is called.
void HandleAbortedRequest(camera3_capture_result_t* capture_result);
// Check whether we should enable constant frame rate according to metadata.
bool ShouldEnableConstantFrameRate(const android::CameraMetadata& metadata);
// Convert |cache_frame_| to the |buffer| with corresponding format.
int WriteStreamBuffer(int stream_index,
int num_streams,
const android::CameraMetadata& metadata,
camera3_stream_buffer_t* buffer);
// Some devices may output invalid image after stream on. Skip frames
// after stream on.
void SkipFramesAfterStreamOn(int num_frames);
// Wait output buffer synced. Return false if fence timeout.
bool WaitGrallocBufferSync(camera3_capture_result_t* capture_result);
// Do not wait buffer sync for aborted requests.
void AbortGrallocBufferSync(camera3_capture_result_t* capture_result);
// Notify shutter event.
void NotifyShutter(uint32_t frame_number);
// Notify request error event.
void NotifyRequestError(uint32_t frame_number);
// Dequeue V4L2 frame buffer.
int DequeueV4L2Buffer(int32_t pattern_mode);
// Enqueue V4L2 frame buffer.
int EnqueueV4L2Buffer();
// Used to notify caller that all requests are handled.
void FlushDone(const base::Callback<void(int)>& callback);
// Variables from CameraClient:
const int device_id_;
const DeviceInfo device_info_;
// Delegate to communicate with camera device. Caller owns the ownership.
V4L2CameraDevice* device_;
// Methods used to call back into the framework.
const camera3_callback_ops_t* callback_ops_;
// Task runner for request thread.
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
// Variables only for RequestHandler:
// The formats used to report to apps.
SupportedFormats qualified_formats_;
// Memory mapped buffers which are shared from |device_|.
std::vector<std::unique_ptr<V4L2FrameBuffer>> input_buffers_;
// Used to convert to different output formats.
CachedFrame input_frame_;
// Handle metadata events and store states. CameraClient takes the
// ownership.
MetadataHandler* metadata_handler_;
// The resolution for stream on.
Size stream_on_resolution_;
// The constant_frame_rate setting for stream on.
bool constant_frame_rate_;
// Current using buffer id for |input_buffers_|.
int current_v4l2_buffer_id_;
// Current buffer timestamp.
uint64_t current_v4l2_buffer_timestamp_;
// Used to notify that flush is called from framework.
bool flush_started_;
// Used to generate test pattern.
std::unique_ptr<TestPattern> test_pattern_;
// Used to enable crop, rotate, and scale capability for portriat preview.
int crop_rotate_scale_degrees_;
// Used to guard |flush_started_|.
base::Lock flush_lock_;
};
std::unique_ptr<RequestHandler> request_handler_;
// Used to handle requests.
base::Thread request_thread_;
// Task runner for request thread.
scoped_refptr<base::SingleThreadTaskRunner> request_task_runner_;
DISALLOW_COPY_AND_ASSIGN(CameraClient);
};
} // namespace cros
#endif // HAL_USB_CAMERA_CLIENT_H_