[go: nahoru, domu]

blob: 087738384f12e497e3192fea78cd42d231e5589b [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// 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_APP_DEVICE_IMPL_H_
#define MEDIA_CAPTURE_VIDEO_CHROMEOS_CAMERA_APP_DEVICE_IMPL_H_
#include <map>
#include <queue>
#include <string>
#include <utility>
#include <vector>
#include "ash/webui/camera_app_ui/document_scanner_service_client.h"
#include "base/containers/queue.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
#include "base/task/single_thread_task_runner.h"
#include "base/timer/elapsed_timer.h"
#include "media/base/video_transformation.h"
#include "media/capture/capture_export.h"
#include "media/capture/mojom/image_capture.mojom.h"
#include "media/capture/video/chromeos/camera_device_delegate.h"
#include "media/capture/video/chromeos/mojom/camera3.mojom.h"
#include "media/capture/video/chromeos/mojom/camera_app.mojom.h"
#include "media/capture/video/chromeos/mojom/camera_common.mojom.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote_set.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/range/range.h"
namespace gpu {
class GpuMemoryBufferImpl;
} // namespace gpu
namespace media {
class CameraDeviceContext;
// TODO(shik): Get the keys from VendorTagOps by names instead (b/130774415).
constexpr uint32_t kPortraitModeVendorKey = 0x80000000;
constexpr uint32_t kPortraitModeSegmentationResultVendorKey = 0x80000001;
// Implementation of CameraAppDevice that is used as the communication bridge
// between Chrome Camera App (CCA) and the ChromeOS Video Capture Device. By
// using this, we can do more complicated operations on cameras which is not
// supported by Chrome API.
class CAPTURE_EXPORT CameraAppDeviceImpl : public cros::mojom::CameraAppDevice {
public:
// TODO(b/244503017): Add definitions for the portrait mode segmentation
// result in the mojom file.
// Retrieve the return code for portrait mode segmentation result from the
// |metadata|.
static int GetPortraitSegResultCode(
const cros::mojom::CameraMetadataPtr* metadata);
explicit CameraAppDeviceImpl(const std::string& device_id);
CameraAppDeviceImpl(const CameraAppDeviceImpl&) = delete;
CameraAppDeviceImpl& operator=(const CameraAppDeviceImpl&) = delete;
~CameraAppDeviceImpl() override;
// Binds the mojo receiver to this implementation.
void BindReceiver(
mojo::PendingReceiver<cros::mojom::CameraAppDevice> receiver);
// All the weak pointers should be retrieved, dereferenced and invalidated on
// the camera device ipc thread.
base::WeakPtr<CameraAppDeviceImpl> GetWeakPtr();
// Resets things which need to be handled on device IPC thread, including
// invalidating all the existing weak pointers, and then triggers |callback|.
// When |should_disable_new_ptrs| is set to true, no more weak pointers can be
// created. It is used when tearing down the CameraAppDeviceImpl instance.
void ResetOnDeviceIpcThread(base::OnceClosure callback,
bool should_disable_new_ptrs);
// Retrieves the fps range if it is specified by the app.
absl::optional<gfx::Range> GetFpsRange();
// Retrieves the corresponding capture resolution which is specified by the
// app.
gfx::Size GetStillCaptureResolution();
// Gets the capture intent which is specified by the app.
cros::mojom::CaptureIntent GetCaptureIntent();
// Delivers the result |metadata| with its |stream_type| to the metadata
// observers.
void OnResultMetadataAvailable(const cros::mojom::CameraMetadataPtr& metadata,
const cros::mojom::StreamType stream_type);
// Notifies the camera event observers that the shutter is finished.
void OnShutterDone();
// Notifies the camera info observers that the camera info is updated.
void OnCameraInfoUpdated(cros::mojom::CameraInfoPtr camera_info);
// Sets the pointer to the camera device context instance associated with the
// opened camera. Used to configure and query camera frame rotation.
void SetCameraDeviceContext(CameraDeviceContext* device_context);
// Detect document corners on the frame given by its gpu memory buffer if it
// is supported.
void MaybeDetectDocumentCorners(std::unique_ptr<gpu::GpuMemoryBufferImpl> gmb,
VideoRotation rotation);
bool IsMultipleStreamsEnabled();
// cros::mojom::CameraAppDevice implementations.
void TakePortraitModePhoto(
mojo::PendingRemote<cros::mojom::StillCaptureResultObserver> observer,
TakePortraitModePhotoCallback callback) override;
void SetFpsRange(const gfx::Range& fps_range,
SetFpsRangeCallback callback) override;
void SetStillCaptureResolution(
const gfx::Size& resolution,
SetStillCaptureResolutionCallback callback) override;
void SetCaptureIntent(cros::mojom::CaptureIntent capture_intent,
SetCaptureIntentCallback callback) override;
void AddResultMetadataObserver(
mojo::PendingRemote<cros::mojom::ResultMetadataObserver> observer,
cros::mojom::StreamType streamType,
AddResultMetadataObserverCallback callback) override;
void AddCameraEventObserver(
mojo::PendingRemote<cros::mojom::CameraEventObserver> observer,
AddCameraEventObserverCallback callback) override;
void SetCameraFrameRotationEnabledAtSource(
bool is_enabled,
SetCameraFrameRotationEnabledAtSourceCallback callback) override;
void GetCameraFrameRotation(GetCameraFrameRotationCallback callback) override;
void RegisterDocumentCornersObserver(
mojo::PendingRemote<cros::mojom::DocumentCornersObserver> observer,
RegisterDocumentCornersObserverCallback callback) override;
void SetMultipleStreamsEnabled(
bool enabled,
SetMultipleStreamsEnabledCallback callback) override;
void RegisterCameraInfoObserver(
mojo::PendingRemote<cros::mojom::CameraInfoObserver> observer,
RegisterCameraInfoObserverCallback callback) override;
absl::optional<PortraitModeCallbacks> ConsumePortraitModeCallbacks();
void SetCropRegion(const gfx::Rect& crop_region,
SetCropRegionCallback callback) override;
void ResetCropRegion(ResetCropRegionCallback callback) override;
std::optional<std::vector<int32_t>> GetCropRegion();
private:
void OnMojoConnectionError();
bool IsCloseToPreviousDetectionRequest();
void DetectDocumentCornersOnMojoThread(
std::unique_ptr<gpu::GpuMemoryBufferImpl> image,
VideoRotation rotation);
void OnDetectedDocumentCornersOnMojoThread(
VideoRotation rotation,
bool success,
const std::vector<gfx::PointF>& corners);
void NotifyPortraitResultOnMojoThread(cros::mojom::Effect effect,
const int32_t status,
media::mojom::BlobPtr blob);
void NotifyShutterDoneOnMojoThread();
void NotifyResultMetadataOnMojoThread(cros::mojom::CameraMetadataPtr metadata,
cros::mojom::StreamType streamType);
void NotifyCameraInfoUpdatedOnMojoThread();
std::string device_id_;
// If it is set to false, no weak pointers for this instance can be generated
// for IPC thread.
bool allow_new_ipc_weak_ptrs_;
mojo::ReceiverSet<cros::mojom::CameraAppDevice> receivers_;
base::Lock camera_info_lock_;
cros::mojom::CameraInfoPtr camera_info_ GUARDED_BY(camera_info_lock_);
// It is used for calls which should run on the mojo thread.
scoped_refptr<base::SingleThreadTaskRunner> mojo_task_runner_;
mojo::Remote<cros::mojom::StillCaptureResultObserver>
portrait_mode_observers_;
base::Lock portrait_mode_callbacks_lock_;
absl::optional<PortraitModeCallbacks> take_portrait_photo_callbacks_
GUARDED_BY(portrait_mode_callbacks_lock_);
// It will be inserted and read from different threads.
base::Lock fps_ranges_lock_;
absl::optional<gfx::Range> specified_fps_range_ GUARDED_BY(fps_ranges_lock_);
// It will be inserted and read from different threads.
base::Lock still_capture_resolution_lock_;
gfx::Size still_capture_resolution_
GUARDED_BY(still_capture_resolution_lock_);
// It will be modified and read from different threads.
base::Lock capture_intent_lock_;
cros::mojom::CaptureIntent capture_intent_ GUARDED_BY(capture_intent_lock_);
// Those maps will be changed and used only on the mojo thread.
std::map<cros::mojom::StreamType,
mojo::RemoteSet<cros::mojom::ResultMetadataObserver>>
stream_to_metadata_observers_map_;
mojo::RemoteSet<cros::mojom::CameraEventObserver> camera_event_observers_;
base::Lock camera_device_context_lock_;
raw_ptr<CameraDeviceContext> camera_device_context_
GUARDED_BY(camera_device_context_lock_);
base::Lock document_corners_observers_lock_;
mojo::RemoteSet<cros::mojom::DocumentCornersObserver>
document_corners_observers_ GUARDED_BY(document_corners_observers_lock_);
bool has_ongoing_document_detection_task_ = false;
std::unique_ptr<base::ElapsedTimer> document_detection_timer_ = nullptr;
mojo::RemoteSet<cros::mojom::CameraInfoObserver> camera_info_observers_;
// Client to connect to document detection service. It should only be
// used/destructed on the Mojo thread.
std::unique_ptr<ash::DocumentScannerServiceClient> document_scanner_service_;
base::Lock multi_stream_lock_;
bool multi_stream_enabled_ GUARDED_BY(multi_stream_lock_) = false;
base::Lock crop_region_lock_;
std::optional<std::vector<int32_t>> crop_region_
GUARDED_BY(crop_region_lock_);
// The weak pointers should be dereferenced and invalidated on camera device
// ipc thread.
base::WeakPtrFactory<CameraAppDeviceImpl> weak_ptr_factory_{this};
// The weak pointers should be dereferenced and invalidated on the Mojo
// thread.
base::WeakPtrFactory<CameraAppDeviceImpl> weak_ptr_factory_for_mojo_{this};
};
} // namespace media
#endif // MEDIA_CAPTURE_VIDEO_CHROMEOS_CAMERA_APP_DEVICE_IMPL_H_