blob: 3f8c72cfb5e0c8c820797b370ddd7cd445833bfa [file] [log] [blame]
// Copyright 2017 The Chromium 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 MEDIA_CAPTURE_VIDEO_CHROMEOS_CAMERA_DEVICE_DELEGATE_H_
#define MEDIA_CAPTURE_VIDEO_CHROMEOS_CAMERA_DEVICE_DELEGATE_H_
#include <memory>
#include <queue>
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "media/capture/video/chromeos/camera_device_context.h"
#include "media/capture/video/chromeos/capture_metadata_dispatcher.h"
#include "media/capture/video/chromeos/mojom/camera3.mojom.h"
#include "media/capture/video/chromeos/mojom/camera_common.mojom.h"
#include "media/capture/video/video_capture_device.h"
#include "media/capture/video_capture_types.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/range/range.h"
namespace media {
class Camera3AController;
class CameraHalDelegate;
class RequestManager;
enum class StreamType : uint64_t {
kPreviewOutput = 0,
kJpegOutput = 1,
kYUVInput = 2,
kYUVOutput = 3,
kRecordingOutput = 4,
kUnknown = 5,
};
// A map to know that each StreamType belongs to which ClientType.
// The index is StreamType value.
constexpr std::array<ClientType, static_cast<int>(StreamType::kUnknown)>
kStreamClientTypeMap = {
ClientType::kPreviewClient, // kPreviewOutput
ClientType::kPreviewClient, // kJpegOutput
ClientType::kPreviewClient, // kYUVInput
ClientType::kPreviewClient, // kYUVOutput
ClientType::kVideoClient, // kRecordingOutput
};
// The metadata might be large so clone a whole metadata might be relatively
// expensive. We only keep the needed data by this structure.
struct ResultMetadata {
ResultMetadata();
~ResultMetadata();
absl::optional<uint8_t> ae_mode;
absl::optional<int32_t> ae_compensation;
absl::optional<uint8_t> af_mode;
absl::optional<uint8_t> awb_mode;
absl::optional<int32_t> brightness;
absl::optional<int32_t> contrast;
absl::optional<int64_t> exposure_time;
absl::optional<float> focus_distance;
absl::optional<int32_t> pan;
absl::optional<int32_t> saturation;
absl::optional<int32_t> sensitivity;
absl::optional<int32_t> sharpness;
absl::optional<int32_t> tilt;
absl::optional<int32_t> zoom;
absl::optional<gfx::Rect> scaler_crop_region;
};
// Returns true if the given stream type is an input stream.
bool IsInputStream(StreamType stream_type);
StreamType StreamIdToStreamType(uint64_t stream_id);
std::string StreamTypeToString(StreamType stream_type);
std::ostream& operator<<(std::ostream& os, StreamType stream_type);
// The interface to register buffer with and send capture request to the
// camera HAL.
class CAPTURE_EXPORT StreamCaptureInterface {
public:
struct Plane {
Plane();
~Plane();
mojo::ScopedHandle fd;
uint32_t stride;
uint32_t offset;
};
virtual ~StreamCaptureInterface() {}
// Sends a capture request to the camera HAL.
virtual void ProcessCaptureRequest(
cros::mojom::Camera3CaptureRequestPtr request,
base::OnceCallback<void(int32_t)> callback) = 0;
// Send flush to cancel all pending requests to the camera HAL.
virtual void Flush(base::OnceCallback<void(int32_t)> callback) = 0;
};
// CameraDeviceDelegate is instantiated on the capture thread where
// AllocateAndStart of VideoCaptureDeviceArcChromeOS runs on. All the methods
// in CameraDeviceDelegate run on |ipc_task_runner_| and hence all the
// access to member variables is sequenced.
//
// CameraDeviceDelegate supports multiple clients.
// It will use the first client for preview stream and photo stream and use
// second client for recording stream.
// The second client will be a virtual camera device which is only used in CCA.
class CAPTURE_EXPORT CameraDeviceDelegate final
: public CaptureMetadataDispatcher::ResultMetadataObserver {
public:
CameraDeviceDelegate(
VideoCaptureDeviceDescriptor device_descriptor,
scoped_refptr<CameraHalDelegate> camera_hal_delegate,
scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner);
~CameraDeviceDelegate() final;
// Delegation methods for the VideoCaptureDevice interface.
void AllocateAndStart(
const base::flat_map<ClientType, VideoCaptureParams>& params,
CameraDeviceContext* device_context);
void StopAndDeAllocate(base::OnceClosure device_close_callback);
void TakePhoto(VideoCaptureDevice::TakePhotoCallback callback);
void GetPhotoState(VideoCaptureDevice::GetPhotoStateCallback callback);
void SetPhotoOptions(mojom::PhotoSettingsPtr settings,
VideoCaptureDevice::SetPhotoOptionsCallback callback);
void ReconfigureStreams(
const base::flat_map<ClientType, VideoCaptureParams>& params);
// Sets the frame rotation angle in |rotation_|. |rotation_| is clockwise
// rotation in degrees, and is passed to |client_| along with the captured
// frames.
void SetRotation(int rotation);
base::WeakPtr<CameraDeviceDelegate> GetWeakPtr();
private:
class StreamCaptureInterfaceImpl;
friend class CameraDeviceDelegateTest;
// Reconfigures the streams to include photo stream according to |settings|.
// Returns true if the reconfigure process is triggered.
bool MaybeReconfigureForPhotoStream(mojom::PhotoSettingsPtr settings);
void TakePhotoImpl();
// Mojo connection error handler.
void OnMojoConnectionError();
// Reconfigure streams for picture taking and recording.
void OnFlushed(bool require_photo,
absl::optional<gfx::Size> new_blob_resolution,
int32_t result);
// Callback method for the Close Mojo IPC call. This method resets the Mojo
// connection and closes the camera device.
void OnClosed(int32_t result);
// Resets the Mojo interface and bindings.
void ResetMojoInterface();
// Creates the Mojo connection to the camera device.
void OnOpenedDevice(int32_t result);
// Initializes the camera HAL. Initialize sets up the Camera3CallbackOps with
// the camera HAL. OnInitialized continues to ConfigureStreams if the
// Initialize call succeeds.
void Initialize();
void OnInitialized(int32_t result);
// ConfigureStreams sets up stream context in |streams_| and configure the
// streams with the camera HAL. OnConfiguredStreams updates |streams_| with
// the stream config returned, and allocates buffers as per |updated_config|
// indicates. If there's no error OnConfiguredStreams notifies
// |client_| the capture has started by calling OnStarted, and proceeds to
// ConstructDefaultRequestSettings.
void ConfigureStreams(bool require_photo,
absl::optional<gfx::Size> new_blob_resolution);
void OnConfiguredStreams(
gfx::Size blob_resolution,
int32_t result,
cros::mojom::Camera3StreamConfigurationPtr updated_config);
// Checks metadata in |static_metadata_| to ensure field
// request.availableCapabilities contains YUV reprocessing and field
// scaler.availableInputOutputFormatsMap contains YUV => BLOB mapping.
// If above checks both pass, fill the max yuv width and height in
// |max_width| and |max_height| and return true if both width and height are
// positive numbers. Return false otherwise.
bool IsYUVReprocessingSupported(int* max_width, int* max_height);
// ConstructDefaultRequestSettings asks the camera HAL for the default request
// settings of the stream in |stream_context_|.
// OnConstructedDefaultRequestSettings sets the request settings in
// |streams_context_|. If there's no error
// OnConstructedDefaultPreviewRequestSettings calls StartPreview to start the
// video capture loop.
// OnConstructDefaultStillCaptureRequestSettings triggers
// |stream_buffer_manager_| to request a still capture.
void ConstructDefaultRequestSettings(StreamType stream_type);
void OnConstructedDefaultPreviewRequestSettings(
cros::mojom::CameraMetadataPtr settings);
void OnConstructedDefaultStillCaptureRequestSettings(
cros::mojom::CameraMetadataPtr settings);
gfx::Size GetBlobResolution(absl::optional<gfx::Size> new_blob_resolution);
// StreamCaptureInterface implementations. These methods are called by
// |stream_buffer_manager_| on |ipc_task_runner_|.
void ProcessCaptureRequest(cros::mojom::Camera3CaptureRequestPtr request,
base::OnceCallback<void(int32_t)> callback);
void Flush(base::OnceCallback<void(int32_t)> callback);
bool SetPointsOfInterest(
const std::vector<mojom::Point2DPtr>& points_of_interest);
// This function gets the TYPE_INT32[3] array of [max, min, step] from static
// metadata by |range_name| and current value of |current|.
mojom::RangePtr GetControlRangeByVendorTagName(
const std::string& range_name,
const absl::optional<int32_t>& current);
// CaptureMetadataDispatcher::ResultMetadataObserver implementation.
void OnResultMetadataAvailable(
uint32_t frame_number,
const cros::mojom::CameraMetadataPtr& result_metadata) final;
void DoGetPhotoState(VideoCaptureDevice::GetPhotoStateCallback callback);
const VideoCaptureDeviceDescriptor device_descriptor_;
// Current configured resolution of BLOB stream.
gfx::Size current_blob_resolution_;
const scoped_refptr<CameraHalDelegate> camera_hal_delegate_;
// Map client type to video capture parameter.
base::flat_map<ClientType, VideoCaptureParams> chrome_capture_params_;
CameraDeviceContext* device_context_;
std::queue<VideoCaptureDevice::TakePhotoCallback> take_photo_callbacks_;
std::unique_ptr<RequestManager> request_manager_;
std::unique_ptr<Camera3AController> camera_3a_controller_;
// Stores the static camera characteristics of the camera device. E.g. the
// supported formats and resolution, various available exposure and apeture
// settings, etc.
cros::mojom::CameraMetadataPtr static_metadata_;
mojo::Remote<cros::mojom::Camera3DeviceOps> device_ops_;
// Where all the Mojo IPC calls takes place.
const scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner_;
base::OnceClosure device_close_callback_;
std::queue<base::OnceClosure> on_reconfigured_callbacks_;
uint32_t device_api_version_;
// States of SetPhotoOptions
bool is_set_awb_mode_;
bool is_set_brightness_;
bool is_set_contrast_;
bool is_set_exposure_compensation_;
bool is_set_exposure_time_;
bool is_set_focus_distance_;
bool is_set_iso_;
bool is_set_pan_;
bool is_set_saturation_;
bool is_set_sharpness_;
bool is_set_tilt_;
bool is_set_zoom_;
std::vector<base::OnceClosure> get_photo_state_queue_;
bool use_digital_zoom_;
float ae_compensation_step_;
// We reply GetPhotoState when |result_metadata_frame_number_| >
// |result_metadata_frame_number_for_photo_state_|. Otherwise javascript API
// getSettings() will get non-updated settings.
// They call GetPhotoState after SetPhotoOptions, we don't have the related
// result metadata that time.
uint32_t current_request_frame_number_;
uint32_t result_metadata_frame_number_for_photo_state_;
uint32_t result_metadata_frame_number_;
ResultMetadata result_metadata_;
gfx::Rect active_array_size_;
base::WeakPtrFactory<CameraDeviceDelegate> weak_ptr_factory_{this};
DISALLOW_IMPLICIT_CONSTRUCTORS(CameraDeviceDelegate);
};
} // namespace media
#endif // MEDIA_CAPTURE_VIDEO_CHROMEOS_CAMERA_DEVICE_DELEGATE_H_