blob: a85d7f5824356f0d6c7fb04e2ec17f9deb96bddc [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_CONTEXT_H_
#define MEDIA_CAPTURE_VIDEO_CHROMEOS_CAMERA_DEVICE_CONTEXT_H_
#include <memory>
#include <string>
#include "base/containers/flat_map.h"
#include "base/sequence_checker.h"
#include "base/synchronization/lock.h"
#include "media/capture/video/video_capture_device.h"
namespace media {
enum class ClientType : uint32_t {
kPreviewClient = 0,
kVideoClient = 1,
};
// A class storing the context of a running CameraDeviceDelegate.
//
// The class is also used to forward/translate events and method calls to a
// given VideoCaptureDevice::Client. This class supposes to have two clients
// at most. One is for preview and another is for video.
class CAPTURE_EXPORT CameraDeviceContext {
public:
// The internal state of the running CameraDeviceDelegate. The state
// transition happens when the corresponding methods are called inside
// CameraDeviceDelegate.
enum class State {
// The camera device is completely stopped. This is the initial state, and
// is also set in OnClosed().
kStopped,
// The camera device is starting and waiting to be initialized.
//
// The kStarting state is set in AllocateAndStart().
kStarting,
// The camera device is initialized and can accept stream configuration
// requests.
//
// The state is transitioned to kInitialized through:
//
// |hal_delegate_|->GetCameraInfo() -> OnGotCameraInfo() ->
// |hal_delegate_|->OpenDevice() -> OnOpenedDevice() ->
// Initialize() -> OnInitialized()
kInitialized,
// The various capture streams are configured and the camera device is ready
// to process capture requests.
//
// The state is transitioned to kStreamConfigured through:
//
// ConfigureStreams() -> OnConfiguredStreams()
kStreamConfigured,
// The camera device is capturing video streams.
//
// The state is transitioned to kCapturing through:
//
// ConstructDefaultRequestSettings() ->
// OnConstructedDefaultRequestSettings() ->
// |stream_buffer_manager_|->StartPreview()
//
// In the kCapturing state the |stream_buffer_manager_| runs the capture
// loop to send capture requests and process capture results.
kCapturing,
// When the camera device is in the kCapturing state, a capture loop is
// constantly running in |stream_buffer_manager_|:
//
// On the StreamBufferManager side, we register and submit a capture
// request whenever a free buffer is available:
//
// RegisterBuffer() -> OnRegisteredBuffer() ->
// ProcessCaptureRequest() -> OnProcessedCaptureRequest()
//
// We get various capture metadata and error notifications from the camera
// HAL through the following callbacks:
//
// ProcessCaptureResult()
// Notify()
// The camera device is going through the shut down process; in order to
// avoid race conditions, no new Mojo messages may be sent to camera HAL in
// the kStopping state.
//
// The kStopping state is set in StopAndDeAllocate().
kStopping,
// The camera device encountered an unrecoverable error and needs to be
// StopAndDeAllocate()'d.
//
// The kError state is set in SetErrorState().
kError,
};
CameraDeviceContext();
~CameraDeviceContext();
bool AddClient(ClientType client_type,
std::unique_ptr<VideoCaptureDevice::Client> client);
void RemoveClient(ClientType client_type);
void SetState(State state);
State GetState();
// Sets state to kError and call |client_->OnError| to tear down the
// VideoCaptureDevice.
void SetErrorState(media::VideoCaptureError error,
const base::Location& from_here,
const std::string& reason);
// Logs |message| to |client_|.
void LogToClient(std::string message);
// Submits the captured camera frame directly in a video capture buffer. No
// buffer copy nor format conversion will be performed on the captured buffer.
// The buffer would be passed to the renderer process directly through
// |client_->OnIncomingCapturedBufferExt|.
void SubmitCapturedVideoCaptureBuffer(
ClientType client_type,
VideoCaptureDevice::Client::Buffer buffer,
const VideoCaptureFormat& frame_format,
base::TimeTicks reference_time,
base::TimeDelta timestamp,
const VideoFrameMetadata& metadata);
// Submits the captured camera frame through a locally-allocated
// GpuMemoryBuffer. The captured buffer would be submitted through
// |client_->OnIncomingCapturedGfxBuffer|, which would perform buffer copy
// and/or format conversion to an I420 SharedMemory-based video capture buffer
// for client consumption.
void SubmitCapturedGpuMemoryBuffer(ClientType client_type,
gfx::GpuMemoryBuffer* buffer,
const VideoCaptureFormat& frame_format,
base::TimeTicks reference_time,
base::TimeDelta timestamp);
void SetSensorOrientation(int sensor_orientation);
void SetScreenRotation(int screen_rotation);
// Controls whether the Chrome OS video capture device applies frame rotation
// according to sensor and UI rotation.
void SetCameraFrameRotationEnabledAtSource(bool is_enabled);
// Gets the accumulated rotation that the camera frame needs to be rotated
// to match the display orientation. This includes the sensor orientation and
// the screen rotation.
int GetCameraFrameRotation();
// Gets whether the camera frame rotation is enabled inside the video capture
// device.
bool IsCameraFrameRotationEnabledAtSource();
// Reserves a video capture buffer from the buffer pool provided by the video
// |client_|. Returns true if the operation succeeds; false otherwise.
bool ReserveVideoCaptureBufferFromPool(
ClientType client_type,
gfx::Size size,
VideoPixelFormat format,
VideoCaptureDevice::Client::Buffer* buffer);
// Returns true if there is a client.
bool HasClient();
private:
friend class RequestManagerTest;
SEQUENCE_CHECKER(sequence_checker_);
// The state the CameraDeviceDelegate currently is in.
State state_;
// Lock to serialize the access to the various camera rotation state variables
// since they are access on multiple threads.
base::Lock rotation_state_lock_;
// Clockwise angle through which the output image needs to be rotated to be
// upright on the device screen in its native orientation. This value should
// be 0, 90, 180, or 270.
int sensor_orientation_ GUARDED_BY(rotation_state_lock_);
// Clockwise screen rotation in degrees. This value should be 0, 90, 180, or
// 270.
int screen_rotation_ GUARDED_BY(rotation_state_lock_);
// Whether the camera frame rotation is enabled inside the video capture
// device.
bool frame_rotation_at_source_ GUARDED_BY(rotation_state_lock_);
base::Lock client_lock_;
// A map for client type and client instance.
base::flat_map<ClientType, std::unique_ptr<VideoCaptureDevice::Client>>
clients_ GUARDED_BY(client_lock_);
};
} // namespace media
#endif // MEDIA_CAPTURE_VIDEO_CHROMEOS_CAMERA_DEVICE_CONTEXT_H_