Commit a138578b authored by Moja Hsu's avatar Moja Hsu Committed by Commit Bot

camera: Support some MediaTrackCapabilities

This CL adds brightness, contrast, saturation, sharpness, pan and tilt
support.

built-in camera of eve. Test pan and tilt on huddly go camera.
Pass CtsCameraTestCases on eve.

Bug: b:148527288
Test: Test brightness, contrast, saturation and sharpness on the
Change-Id: Id3d277889f0dde482cf8d546b7b226d1c0f0e5f3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2164347
Commit-Queue: Hsu Wei-Cheng <mojahsu@chromium.org>
Reviewed-by: default avatarShik Chen <shik@chromium.org>
Reviewed-by: default avatarGuido Urdaneta <guidou@chromium.org>
Reviewed-by: default avatarWei Lee <wtlee@chromium.org>
Cr-Commit-Position: refs/heads/master@{#771692}
parent e46af0bc
......@@ -269,6 +269,7 @@ jumbo_component("capture_lib") {
"video/chromeos/camera_hal_dispatcher_impl.h",
"video/chromeos/camera_metadata_utils.cc",
"video/chromeos/camera_metadata_utils.h",
"video/chromeos/capture_metadata_dispatcher.h",
"video/chromeos/display_rotation_observer.cc",
"video/chromeos/display_rotation_observer.h",
"video/chromeos/gpu_memory_buffer_tracker.cc",
......
......@@ -32,6 +32,19 @@ namespace media {
namespace {
constexpr char kBrightness[] = "com.google.control.brightness";
constexpr char kBrightnessRange[] = "com.google.control.brightnessRange";
constexpr char kContrast[] = "com.google.control.contrast";
constexpr char kContrastRange[] = "com.google.control.contrastRange";
constexpr char kPan[] = "com.google.control.pan";
constexpr char kPanRange[] = "com.google.control.panRange";
constexpr char kSaturation[] = "com.google.control.saturation";
constexpr char kSaturationRange[] = "com.google.control.saturationRange";
constexpr char kSharpness[] = "com.google.control.sharpness";
constexpr char kSharpnessRange[] = "com.google.control.sharpnessRange";
constexpr char kTilt[] = "com.google.control.tilt";
constexpr char kTiltRange[] = "com.google.control.tiltRange";
std::pair<int32_t, int32_t> GetTargetFrameRateRange(
const cros::mojom::CameraMetadataPtr& static_metadata,
int target_frame_rate,
......@@ -216,6 +229,9 @@ class CameraDeviceDelegate::StreamCaptureInterfaceImpl final
const base::WeakPtr<CameraDeviceDelegate> camera_device_delegate_;
};
ResultMetadata::ResultMetadata() = default;
ResultMetadata::~ResultMetadata() = default;
CameraDeviceDelegate::CameraDeviceDelegate(
VideoCaptureDeviceDescriptor device_descriptor,
scoped_refptr<CameraHalDelegate> camera_hal_delegate,
......@@ -233,6 +249,7 @@ void CameraDeviceDelegate::AllocateAndStart(
CameraDeviceContext* device_context) {
DCHECK(ipc_task_runner_->BelongsToCurrentThread());
got_result_metadata_ = false;
chrome_capture_params_ = params;
device_context_ = device_context;
device_context_->SetState(CameraDeviceContext::State::kStarting);
......@@ -324,38 +341,13 @@ void CameraDeviceDelegate::GetPhotoState(
VideoCaptureDevice::GetPhotoStateCallback callback) {
DCHECK(ipc_task_runner_->BelongsToCurrentThread());
auto photo_state = mojo::CreateEmptyPhotoState();
if (!device_context_ ||
(device_context_->GetState() !=
CameraDeviceContext::State::kStreamConfigured &&
device_context_->GetState() != CameraDeviceContext::State::kCapturing)) {
std::move(callback).Run(std::move(photo_state));
if (!got_result_metadata_) {
get_photo_state_queue_.push_back(
base::BindOnce(&CameraDeviceDelegate::DoGetPhotoState,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
return;
}
std::vector<gfx::Size> blob_resolutions;
GetStreamResolutions(
static_metadata_, cros::mojom::Camera3StreamType::CAMERA3_STREAM_OUTPUT,
cros::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_BLOB, &blob_resolutions);
if (blob_resolutions.empty()) {
std::move(callback).Run(std::move(photo_state));
return;
}
// Sets the correct range of min/max resolution in order to bypass checks that
// the resolution caller request should fall within the range when taking
// photos. And since we are not actually use the mechanism to get other
// resolutions, we set the step to 0.0 here.
photo_state->width->current = current_blob_resolution_.width();
photo_state->width->min = blob_resolutions.front().width();
photo_state->width->max = blob_resolutions.back().width();
photo_state->width->step = 0.0;
photo_state->height->current = current_blob_resolution_.height();
photo_state->height->min = blob_resolutions.front().height();
photo_state->height->max = blob_resolutions.back().height();
photo_state->height->step = 0.0;
std::move(callback).Run(std::move(photo_state));
DoGetPhotoState(std::move(callback));
}
// On success, invokes |callback| with value |true|. On failure, drops
......@@ -375,6 +367,28 @@ void CameraDeviceDelegate::SetPhotoOptions(
return;
}
auto set_vendor_int = [&](const std::string& name, bool has_field,
double value) {
if (!has_field) {
return;
}
const VendorTagInfo* info =
camera_hal_delegate_->GetVendorTagInfoByName(name);
if (info == nullptr)
return;
std::vector<uint8_t> temp(sizeof(int32_t));
auto* temp_ptr = reinterpret_cast<int32_t*>(temp.data());
*temp_ptr = value;
request_manager_->SetRepeatingCaptureMetadata(info->tag, info->type, 1,
std::move(temp));
};
set_vendor_int(kBrightness, settings->has_brightness, settings->brightness);
set_vendor_int(kContrast, settings->has_contrast, settings->contrast);
set_vendor_int(kPan, settings->has_pan, settings->pan);
set_vendor_int(kSaturation, settings->has_saturation, settings->saturation);
set_vendor_int(kSharpness, settings->has_sharpness, settings->sharpness);
set_vendor_int(kTilt, settings->has_tilt, settings->tilt);
bool is_resolution_specified = settings->has_width && settings->has_height;
bool should_reconfigure_streams =
is_resolution_specified && (current_blob_resolution_.IsEmpty() ||
......@@ -483,6 +497,9 @@ void CameraDeviceDelegate::OnClosed(int32_t result) {
device_context_->LogToClient(std::string("Failed to close device: ") +
base::safe_strerror(-result));
}
if (request_manager_) {
request_manager_->RemoveResultMetadataObserver(this);
}
ResetMojoInterface();
device_context_ = nullptr;
current_blob_resolution_.SetSize(0, 0);
......@@ -548,6 +565,7 @@ void CameraDeviceDelegate::Initialize() {
device_ops_->Initialize(
std::move(callback_ops),
base::BindOnce(&CameraDeviceDelegate::OnInitialized, GetWeakPtr()));
request_manager_->AddResultMetadataObserver(this);
}
void CameraDeviceDelegate::OnInitialized(int32_t result) {
......@@ -1046,4 +1064,117 @@ bool CameraDeviceDelegate::SetPointsOfInterest(
return true;
}
mojom::RangePtr CameraDeviceDelegate::GetControlRangeByVendorTagName(
const std::string& range_name,
const base::Optional<int32_t>& current) {
const VendorTagInfo* info =
camera_hal_delegate_->GetVendorTagInfoByName(range_name);
if (info == nullptr) {
return mojom::Range::New();
}
auto static_val =
GetMetadataEntryAsSpan<int32_t>(static_metadata_, info->tag);
if (static_val.size() != 3) {
return mojom::Range::New();
}
if (!current) {
return mojom::Range::New();
}
mojom::RangePtr range = mojom::Range::New();
range->min = static_val[0];
range->max = static_val[1];
range->step = static_val[2];
range->current = current.value();
return range;
}
void CameraDeviceDelegate::OnResultMetadataAvailable(
const cros::mojom::CameraMetadataPtr& result_metadata) {
DCHECK(ipc_task_runner_->BelongsToCurrentThread());
auto get_vendor_int =
[&](const std::string& name,
const cros::mojom::CameraMetadataPtr& result_metadata,
base::Optional<int32_t>* returned_value) {
returned_value->reset();
const VendorTagInfo* info =
camera_hal_delegate_->GetVendorTagInfoByName(name);
if (info == nullptr)
return;
auto val = GetMetadataEntryAsSpan<int32_t>(result_metadata, info->tag);
if (val.size() == 1)
*returned_value = val[0];
};
get_vendor_int(kBrightness, result_metadata, &result_metadata_.brightness);
get_vendor_int(kContrast, result_metadata, &result_metadata_.contrast);
get_vendor_int(kPan, result_metadata, &result_metadata_.pan);
get_vendor_int(kSaturation, result_metadata, &result_metadata_.saturation);
get_vendor_int(kSharpness, result_metadata, &result_metadata_.sharpness);
get_vendor_int(kTilt, result_metadata, &result_metadata_.tilt);
if (!got_result_metadata_) {
for (auto& request : get_photo_state_queue_)
ipc_task_runner_->PostTask(FROM_HERE, std::move(request));
get_photo_state_queue_.clear();
got_result_metadata_ = true;
}
}
void CameraDeviceDelegate::DoGetPhotoState(
VideoCaptureDevice::GetPhotoStateCallback callback) {
DCHECK(ipc_task_runner_->BelongsToCurrentThread());
auto photo_state = mojo::CreateEmptyPhotoState();
if (!device_context_ ||
(device_context_->GetState() !=
CameraDeviceContext::State::kStreamConfigured &&
device_context_->GetState() != CameraDeviceContext::State::kCapturing)) {
std::move(callback).Run(std::move(photo_state));
return;
}
std::vector<gfx::Size> blob_resolutions;
GetStreamResolutions(
static_metadata_, cros::mojom::Camera3StreamType::CAMERA3_STREAM_OUTPUT,
cros::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_BLOB, &blob_resolutions);
if (blob_resolutions.empty()) {
std::move(callback).Run(std::move(photo_state));
return;
}
// Sets the correct range of min/max resolution in order to bypass checks that
// the resolution caller request should fall within the range when taking
// photos. And since we are not actually use the mechanism to get other
// resolutions, we set the step to 0.0 here.
photo_state->width->current = current_blob_resolution_.width();
photo_state->width->min = blob_resolutions.front().width();
photo_state->width->max = blob_resolutions.back().width();
photo_state->width->step = 0.0;
photo_state->height->current = current_blob_resolution_.height();
photo_state->height->min = blob_resolutions.front().height();
photo_state->height->max = blob_resolutions.back().height();
photo_state->height->step = 0.0;
photo_state->brightness = GetControlRangeByVendorTagName(
kBrightnessRange, result_metadata_.brightness);
photo_state->contrast =
GetControlRangeByVendorTagName(kContrastRange, result_metadata_.contrast);
photo_state->pan =
GetControlRangeByVendorTagName(kPanRange, result_metadata_.pan);
photo_state->saturation = GetControlRangeByVendorTagName(
kSaturationRange, result_metadata_.saturation);
photo_state->sharpness = GetControlRangeByVendorTagName(
kSharpnessRange, result_metadata_.sharpness);
photo_state->tilt =
GetControlRangeByVendorTagName(kTiltRange, result_metadata_.tilt);
std::move(callback).Run(std::move(photo_state));
}
} // namespace media
......@@ -11,6 +11,7 @@
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/single_thread_task_runner.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"
......@@ -35,6 +36,20 @@ enum class StreamType : uint64_t {
kUnknown,
};
// 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();
base::Optional<int32_t> brightness;
base::Optional<int32_t> contrast;
base::Optional<int32_t> pan;
base::Optional<int32_t> saturation;
base::Optional<int32_t> sharpness;
base::Optional<int32_t> tilt;
};
// Returns true if the given stream type is an input stream.
bool IsInputStream(StreamType stream_type);
......@@ -71,7 +86,8 @@ class CAPTURE_EXPORT StreamCaptureInterface {
// 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.
class CAPTURE_EXPORT CameraDeviceDelegate final {
class CAPTURE_EXPORT CameraDeviceDelegate final
: public CaptureMetadataDispatcher::ResultMetadataObserver {
public:
CameraDeviceDelegate(
VideoCaptureDeviceDescriptor device_descriptor,
......@@ -79,7 +95,7 @@ class CAPTURE_EXPORT CameraDeviceDelegate final {
scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner,
CameraAppDeviceImpl* camera_app_device);
~CameraDeviceDelegate();
~CameraDeviceDelegate() final;
// Delegation methods for the VideoCaptureDevice interface.
void AllocateAndStart(const VideoCaptureParams& params,
......@@ -175,6 +191,18 @@ class CAPTURE_EXPORT CameraDeviceDelegate final {
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 base::Optional<int32_t>& current);
// CaptureMetadataDispatcher::ResultMetadataObserver implementation.
void OnResultMetadataAvailable(
const cros::mojom::CameraMetadataPtr& result_metadata) final;
void DoGetPhotoState(VideoCaptureDevice::GetPhotoStateCallback callback);
const VideoCaptureDeviceDescriptor device_descriptor_;
// Current configured resolution of BLOB stream.
......@@ -208,6 +236,11 @@ class CAPTURE_EXPORT CameraDeviceDelegate final {
CameraAppDeviceImpl* camera_app_device_; // Weak.
// GetPhotoState requests waiting for |got_result_metadata_| to be served.
std::vector<base::OnceClosure> get_photo_state_queue_;
bool got_result_metadata_;
ResultMetadata result_metadata_;
base::WeakPtrFactory<CameraDeviceDelegate> weak_ptr_factory_{this};
DISALLOW_IMPLICIT_CONSTRUCTORS(CameraDeviceDelegate);
......
......@@ -364,6 +364,11 @@ cros::mojom::CameraInfoPtr CameraHalDelegate::GetCameraInfoFromDeviceId(
return it->second.Clone();
}
const VendorTagInfo* CameraHalDelegate::GetVendorTagInfoByName(
const std::string& full_name) {
return vendor_tag_ops_delegate_.GetInfoByName(full_name);
}
void CameraHalDelegate::OpenDevice(
int32_t camera_id,
mojo::PendingReceiver<cros::mojom::Camera3DeviceOps> device_ops_receiver,
......
......@@ -85,6 +85,8 @@ class CAPTURE_EXPORT CameraHalDelegate final
cros::mojom::CameraInfoPtr GetCameraInfoFromDeviceId(
const std::string& device_id);
const VendorTagInfo* GetVendorTagInfoByName(const std::string& full_name);
private:
friend class base::RefCountedThreadSafe<CameraHalDelegate>;
......
// Copyright 2020 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_CAPTURE_METADATA_DISPATCHER_H_
#define MEDIA_CAPTURE_VIDEO_CHROMEOS_CAPTURE_METADATA_DISPATCHER_H_
#include "media/capture/capture_export.h"
#include "media/capture/video/chromeos/mojom/camera_common.mojom.h"
namespace media {
// Interface that provides API to let Camera3AController and
// CameraDeviceDelegate to update the metadata that will be sent with capture
// request.
class CAPTURE_EXPORT CaptureMetadataDispatcher {
public:
class ResultMetadataObserver {
public:
virtual ~ResultMetadataObserver() {}
virtual void OnResultMetadataAvailable(
const cros::mojom::CameraMetadataPtr&) = 0;
};
virtual ~CaptureMetadataDispatcher() {}
virtual void AddResultMetadataObserver(ResultMetadataObserver* observer) = 0;
virtual void RemoveResultMetadataObserver(
ResultMetadataObserver* observer) = 0;
virtual void SetCaptureMetadata(cros::mojom::CameraMetadataTag tag,
cros::mojom::EntryType type,
size_t count,
std::vector<uint8_t> value) = 0;
virtual void SetRepeatingCaptureMetadata(cros::mojom::CameraMetadataTag tag,
cros::mojom::EntryType type,
size_t count,
std::vector<uint8_t> value) = 0;
virtual void UnsetRepeatingCaptureMetadata(
cros::mojom::CameraMetadataTag tag) = 0;
};
} // namespace media
#endif // MEDIA_CAPTURE_VIDEO_CHROMEOS_CAPTURE_METADATA_DISPATCHER_H_
......@@ -17,6 +17,7 @@
#include "media/capture/mojom/image_capture.mojom.h"
#include "media/capture/video/chromeos/camera_app_device_impl.h"
#include "media/capture/video/chromeos/camera_device_delegate.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_app.mojom.h"
#include "media/capture/video/chromeos/request_builder.h"
......@@ -44,32 +45,6 @@ constexpr int32_t kMinConfiguredStreams = 1;
// Maximum configured streams could contain two optional YUV streams.
constexpr int32_t kMaxConfiguredStreams = 4;
// Interface that provides API to let Camera3AController to update the metadata
// that will be sent with capture request.
class CAPTURE_EXPORT CaptureMetadataDispatcher {
public:
class ResultMetadataObserver {
public:
virtual ~ResultMetadataObserver() {}
virtual void OnResultMetadataAvailable(
const cros::mojom::CameraMetadataPtr&) = 0;
};
virtual ~CaptureMetadataDispatcher() {}
virtual void AddResultMetadataObserver(ResultMetadataObserver* observer) = 0;
virtual void RemoveResultMetadataObserver(
ResultMetadataObserver* observer) = 0;
virtual void SetCaptureMetadata(cros::mojom::CameraMetadataTag tag,
cros::mojom::EntryType type,
size_t count,
std::vector<uint8_t> value) = 0;
virtual void SetRepeatingCaptureMetadata(cros::mojom::CameraMetadataTag tag,
cros::mojom::EntryType type,
size_t count,
std::vector<uint8_t> value) = 0;
virtual void UnsetRepeatingCaptureMetadata(
cros::mojom::CameraMetadataTag tag) = 0;
};
// RequestManager is responsible for managing the flow for sending capture
// requests and receiving capture results. Having RequestBuilder to build
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment