blob: 08a55a6ffdc37cd03a4068fecdb62bf54563b874 [file] [log] [blame] [edit]
/*
* Copyright 2021 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "common/camera_hal3_helpers.h"
#include <camera/camera_metadata.h>
#include <algorithm>
#include <cstdint>
#include <optional>
#include <utility>
#include <base/json/json_writer.h>
#include <base/notreached.h>
#include <base/values.h>
#include <hardware/camera3.h>
#include <sync/sync.h>
#include "common/camera_buffer_handle.h"
#include "common/common_tracing.h"
#include "cros-camera/camera_metadata_utils.h"
namespace cros {
namespace {
base::Value::Dict ToValueDict(const camera3_stream_t* stream) {
if (!stream) {
return base::Value::Dict();
}
base::Value::Dict s;
s.Set("stream_type", stream->stream_type);
s.Set("width", base::checked_cast<int>(stream->width));
s.Set("height", base::checked_cast<int>(stream->height));
s.Set("format", stream->format);
s.Set("usage", base::checked_cast<int>(stream->usage));
s.Set("max_buffers", base::checked_cast<int>(stream->max_buffers));
s.Set("data_space", stream->data_space);
s.Set("rotation", stream->rotation);
if (stream->physical_camera_id) {
s.Set("physical_camera_id", stream->physical_camera_id);
}
return s;
}
base::Value::Dict ToValueDict(const Camera3StreamBuffer& buffer) {
base::Value::Dict b;
b.Set("stream", ToValueDict(buffer.stream()));
b.Set("status", buffer.status());
b.Set("acquire_fence", buffer.acquire_fence());
b.Set("release_fence", buffer.release_fence());
return b;
}
perfetto::StaticString GetBufferDirectionStr(
Camera3StreamBuffer::Direction dir) {
switch (dir) {
case Camera3StreamBuffer::Direction::kInput:
return perfetto::StaticString("input");
case Camera3StreamBuffer::Direction::kOutput:
return perfetto::StaticString("output");
case Camera3StreamBuffer::Direction::kInvalidDirection:
return perfetto::StaticString("unknown");
}
}
perfetto::StaticString GetBufferEventStr(Camera3StreamBuffer::Type type) {
switch (type) {
case Camera3StreamBuffer::Type::kRequest:
return perfetto::StaticString("Request Buffer");
case Camera3StreamBuffer::Type::kResult:
return perfetto::StaticString("Result Buffer");
case Camera3StreamBuffer::Type::kInvalidType:
return perfetto::StaticString("Unknown Buffer");
}
}
} // namespace
Rect<uint32_t> GetCenteringFullCrop(Size size,
uint32_t aspect_ratio_x,
uint32_t aspect_ratio_y) {
uint32_t crop_width = size.width;
uint32_t crop_height = size.height;
if (size.width * aspect_ratio_y >= size.height * aspect_ratio_x) {
crop_width = size.height * aspect_ratio_x / aspect_ratio_y;
} else {
crop_height = size.width * aspect_ratio_y / aspect_ratio_x;
}
uint32_t dx = (size.width - crop_width) / 2;
uint32_t dy = (size.height - crop_height) / 2;
return Rect<uint32_t>(dx, dy, crop_width, crop_height);
}
bool AddListItemToMetadataTag(android::CameraMetadata* metadata,
uint32_t tag,
int32_t item) {
camera_metadata_entry_t entry = metadata->find(tag);
if (entry.count == 0) {
const int32_t data[] = {item};
return metadata->update(tag, data, 1) == 0;
}
const int32_t* begin = entry.data.i32;
const int32_t* end = entry.data.i32 + entry.count;
if (std::find(begin, end, item) != end) {
return true;
}
std::vector<int32_t> data(begin, end);
data.push_back(item);
return metadata->update(tag, data.data(), data.size()) == 0;
}
bool WaitOnAndClearReleaseFence(camera3_stream_buffer_t& buffer,
int timeout_ms) {
if (buffer.release_fence == -1) {
return true;
}
if (sync_wait(buffer.release_fence, timeout_ms) != 0) {
return false;
}
close(buffer.release_fence);
buffer.release_fence = -1;
return true;
}
int32_t GetPartialResultCount(const camera_metadata_t* metadata) {
std::optional<int32_t> partial_result_count =
GetRoMetadata<int32_t>(metadata, ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
return partial_result_count.value_or(1);
}
//
// Camera3StreamBuffer implementations.
//
// static
Camera3StreamBuffer Camera3StreamBuffer::MakeRequestInput(
const camera3_stream_buffer_t& stream_buffer) {
return Camera3StreamBuffer(stream_buffer, Camera3StreamBuffer::Type::kRequest,
Camera3StreamBuffer::Direction::kInput);
}
// static
Camera3StreamBuffer Camera3StreamBuffer::MakeRequestOutput(
const camera3_stream_buffer_t& stream_buffer) {
return Camera3StreamBuffer(stream_buffer, Camera3StreamBuffer::Type::kRequest,
Camera3StreamBuffer::Direction::kOutput);
}
// static
Camera3StreamBuffer Camera3StreamBuffer::MakeResultInput(
const camera3_stream_buffer_t& stream_buffer) {
return Camera3StreamBuffer(stream_buffer, Camera3StreamBuffer::Type::kResult,
Camera3StreamBuffer::Direction::kInput);
}
// static
Camera3StreamBuffer Camera3StreamBuffer::MakeResultOutput(
const camera3_stream_buffer_t& stream_buffer) {
return Camera3StreamBuffer(stream_buffer, Camera3StreamBuffer::Type::kResult,
Camera3StreamBuffer::Direction::kOutput);
}
Camera3StreamBuffer::~Camera3StreamBuffer() {
Invalidate();
}
Camera3StreamBuffer::Camera3StreamBuffer(Camera3StreamBuffer&& other) {
*this = std::move(other);
}
Camera3StreamBuffer& Camera3StreamBuffer::operator=(
Camera3StreamBuffer&& other) {
if (this != &other) {
Invalidate();
type_ = other.type_;
dir_ = other.dir_;
raw_buffer_ = other.raw_buffer_;
lock_container_ = other.lock_container_;
trace_started_ = other.trace_started_;
other.type_ = Type::kInvalidType;
other.dir_ = Direction::kInvalidDirection;
other.raw_buffer_ = kInvalidRawBuffer;
other.lock_container_ = nullptr;
other.trace_started_ = false;
}
return *this;
}
void Camera3StreamBuffer::Invalidate() {
EndTracing();
raw_buffer_ = kInvalidRawBuffer;
type_ = Type::kInvalidType;
dir_ = Direction::kInvalidDirection;
}
void Camera3StreamBuffer::StartTracing(int frame_number) {
if (!is_valid() || trace_started_) {
return;
}
TRACE_COMMON_EVENT("AttachBuffer", perfetto::Flow::ProcessScoped(flow_id()));
TRACE_COMMON_BEGIN(
GetBufferEventStr(type_),
perfetto::Track(reinterpret_cast<uintptr_t>(*raw_buffer_.buffer)),
"frame_number", frame_number, "direction", GetBufferDirectionStr(dir_),
"stream", reinterpret_cast<uintptr_t>(raw_buffer_.stream), "width",
raw_buffer_.stream->width, "height", raw_buffer_.stream->height, "format",
raw_buffer_.stream->format);
trace_started_ = true;
}
void Camera3StreamBuffer::EndTracing() {
if (!is_valid() || !trace_started_) {
return;
}
TRACE_COMMON_EVENT("DetachBuffer",
perfetto::TerminatingFlow::ProcessScoped(flow_id()));
TRACE_COMMON_END(
perfetto::Track(reinterpret_cast<uintptr_t>(*raw_buffer_.buffer)));
trace_started_ = false;
}
void Camera3StreamBuffer::LockAndFill(camera3_stream_buffer_t* container) {
CHECK_EQ(lock_container_, nullptr);
CHECK(container);
*container = raw_buffer_;
lock_container_ = container;
}
void Camera3StreamBuffer::Unlock() {
CHECK(lock_container_);
raw_buffer_ = *lock_container_;
lock_container_ = nullptr;
}
Camera3StreamBuffer::Camera3StreamBuffer(
const camera3_stream_buffer_t& stream_buf, Type type, Direction dir)
: raw_buffer_(stream_buf), type_(type), dir_(dir) {
if (!is_valid()) {
return;
}
// Some camera HAL may use their own storage to hold |buffer_handle_t*|s in
// the capture results and it doesn't out-live the whole result callback
// sequence. Fix them to our maintained storage so we can pass on the buffer
// object safely.
auto* handle = camera_buffer_handle_t::FromBufferHandle(*raw_buffer_.buffer);
CHECK(handle);
raw_buffer_.buffer = const_cast<buffer_handle_t*>(&handle->self);
}
//
// Camera3StreamConfiguration implementations.
//
Camera3StreamConfiguration::Camera3StreamConfiguration(
const camera3_stream_configuration_t& stream_list,
const StreamEffectMap* stream_effects_map)
: streams_(stream_list.streams,
stream_list.streams + stream_list.num_streams),
operation_mode_(stream_list.operation_mode),
session_parameters_(stream_list.session_parameters),
stream_effects_map_(stream_effects_map) {}
base::span<camera3_stream_t* const> Camera3StreamConfiguration::GetStreams()
const {
return {streams_.data(), streams_.size()};
}
bool Camera3StreamConfiguration::SetStreams(
base::span<camera3_stream_t* const> streams) {
if (IsLocked()) {
LOGF(ERROR) << "Cannot set streams when locked";
return false;
}
streams_.clear();
streams_.resize(streams.size());
std::copy(streams.begin(), streams.end(), streams_.begin());
return true;
}
bool Camera3StreamConfiguration::AppendStream(camera3_stream_t* stream) {
if (IsLocked()) {
LOGF(ERROR) << "Cannot append streams when locked";
return false;
}
streams_.push_back(stream);
return true;
}
bool Camera3StreamConfiguration::RemoveStream(const camera3_stream_t* stream) {
if (IsLocked()) {
LOGF(ERROR) << "Cannot remove streams when locked";
return false;
}
auto it = std::find(streams_.begin(), streams_.end(), stream);
if (it == streams_.end()) {
LOGF(ERROR) << "Cannot find the stream to remove";
return false;
}
streams_.erase(it);
return true;
}
bool Camera3StreamConfiguration::SetSessionParameters(
const camera_metadata_t* session_parameters) {
if (IsLocked()) {
LOGF(ERROR) << "Cannot set session parameters when locked";
return false;
}
session_parameters_ = session_parameters;
return true;
}
camera3_stream_configuration_t* Camera3StreamConfiguration::Lock() {
CHECK(!IsLocked());
raw_configuration_ = camera3_stream_configuration_t{
.num_streams = static_cast<uint32_t>(streams_.size()),
.streams = streams_.data(),
.operation_mode = operation_mode_,
.session_parameters = session_parameters_};
return &raw_configuration_.value();
}
std::string Camera3StreamConfiguration::ToJsonString() const {
base::Value::List val;
for (const auto* stream : GetStreams()) {
val.Append(ToValueDict(stream));
}
std::string json_string;
if (!base::JSONWriter::WriteWithOptions(
val, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json_string)) {
LOGF(ERROR) << "Cannot convert stream configurations to JSON string";
return std::string();
}
return json_string;
}
void Camera3StreamConfiguration::PopulateEventAnnotation(
perfetto::EventContext& ctx) const {
ctx.AddDebugAnnotation("stream_configurations", ToJsonString());
}
void Camera3StreamConfiguration::Unlock() {
raw_configuration_.reset();
}
bool Camera3StreamConfiguration::IsLocked() const {
return raw_configuration_.has_value();
}
//
// Camera3CaptureDescriptor implementations.
//
Camera3CaptureDescriptor::Camera3CaptureDescriptor(
const camera3_capture_request_t& request)
: type_(Type::kCaptureRequest),
frame_number_(request.frame_number),
num_physcam_metadata_(request.num_physcam_settings),
physcam_ids_(request.physcam_id),
physcam_metadata_(request.physcam_settings) {
if (request.settings != nullptr) {
metadata_.acquire(clone_camera_metadata(request.settings));
}
if (request.input_buffer) {
SetInputBuffer(
Camera3StreamBuffer::MakeRequestInput(*request.input_buffer));
}
if (request.num_output_buffers > 0) {
output_buffers_.reserve(request.num_output_buffers);
for (int i = 0; i < request.num_output_buffers; ++i) {
AppendOutputBuffer(Camera3StreamBuffer::MakeRequestOutput(
*(request.output_buffers + i)));
}
}
}
Camera3CaptureDescriptor::Camera3CaptureDescriptor(
const camera3_capture_result_t& result)
: type_(Type::kCaptureResult),
frame_number_(result.frame_number),
partial_result_(result.partial_result),
num_physcam_metadata_(result.num_physcam_metadata),
physcam_ids_(result.physcam_ids),
physcam_metadata_(result.physcam_metadata) {
if (result.result != nullptr) {
metadata_.acquire(clone_camera_metadata(result.result));
}
if (result.input_buffer) {
SetInputBuffer(Camera3StreamBuffer::MakeResultInput(*result.input_buffer));
}
if (result.num_output_buffers > 0) {
output_buffers_.reserve(result.num_output_buffers);
for (int i = 0; i < result.num_output_buffers; ++i) {
AppendOutputBuffer(
Camera3StreamBuffer::MakeResultOutput(*(result.output_buffers + i)));
}
}
}
Camera3CaptureDescriptor::~Camera3CaptureDescriptor() {
Unlock();
Invalidate();
}
Camera3CaptureDescriptor::Camera3CaptureDescriptor(
Camera3CaptureDescriptor&& other) {
*this = std::move(other);
}
Camera3CaptureDescriptor& Camera3CaptureDescriptor::operator=(
Camera3CaptureDescriptor&& other) {
if (this != &other) {
Invalidate();
type_ = other.type_;
frame_number_ = other.frame_number_;
// metadata_.isEmpty() doesn't differentiate a nullptr metadata from a
// valid metadata with zero entry count. We want to move the latter while
// avoid copying the former to avoid the log spams in metadata_.acquire().
camera_metadata_t* m = other.metadata_.release();
if (m) {
metadata_.acquire(m);
}
input_buffer_ = std::move(other.input_buffer_);
output_buffers_ = std::move(other.output_buffers_);
partial_result_ = other.partial_result_;
num_physcam_metadata_ = other.num_physcam_metadata_;
physcam_ids_ = other.physcam_ids_;
physcam_metadata_ = other.physcam_metadata_;
feature_metadata_ = std::move(other.feature_metadata_);
raw_descriptor_ = std::move(other.raw_descriptor_);
other.Invalidate();
}
return *this;
}
template <>
base::span<const uint8_t> Camera3CaptureDescriptor::GetMetadata(
uint32_t tag) const {
camera_metadata_ro_entry_t entry = metadata_.find(tag);
if (entry.count == 0) {
return base::span<const uint8_t>();
}
return base::span<const uint8_t>(entry.data.u8, entry.count);
}
template <>
base::span<const int32_t> Camera3CaptureDescriptor::GetMetadata(
uint32_t tag) const {
camera_metadata_ro_entry_t entry = metadata_.find(tag);
if (entry.count == 0) {
return base::span<const int32_t>();
}
return base::span<const int32_t>(entry.data.i32, entry.count);
}
template <>
base::span<const float> Camera3CaptureDescriptor::GetMetadata(
uint32_t tag) const {
camera_metadata_ro_entry_t entry = metadata_.find(tag);
if (entry.count == 0) {
return base::span<const float>();
}
return base::span<const float>(entry.data.f, entry.count);
}
template <>
base::span<const double> Camera3CaptureDescriptor::GetMetadata(
uint32_t tag) const {
camera_metadata_ro_entry_t entry = metadata_.find(tag);
if (entry.count == 0) {
return base::span<const double>();
}
return base::span<const double>(entry.data.d, entry.count);
}
template <>
base::span<const int64_t> Camera3CaptureDescriptor::GetMetadata(
uint32_t tag) const {
camera_metadata_ro_entry_t entry = metadata_.find(tag);
if (entry.count == 0) {
return base::span<const int64_t>();
}
return base::span<const int64_t>(entry.data.i64, entry.count);
}
template <>
base::span<const camera_metadata_rational_t>
Camera3CaptureDescriptor::GetMetadata(uint32_t tag) const {
camera_metadata_ro_entry_t entry = metadata_.find(tag);
if (entry.count == 0) {
return base::span<const camera_metadata_rational_t>();
}
return base::span<const camera_metadata_rational_t>(entry.data.r,
entry.count);
}
bool Camera3CaptureDescriptor::AppendMetadata(
const camera_metadata_t* metadata) {
if (IsLocked()) {
LOGF(ERROR) << "Cannot update metadata when locked";
return false;
}
auto ret = metadata_.append(metadata);
return ret == 0;
}
bool Camera3CaptureDescriptor::DeleteMetadata(uint32_t tag) {
if (IsLocked()) {
LOGF(ERROR) << "Cannot delete metadata when locked";
return false;
}
auto ret = metadata_.erase(tag);
return ret == 0;
}
bool Camera3CaptureDescriptor::SetMetadata(const camera_metadata_t* metadata) {
if (IsLocked()) {
LOGF(ERROR) << "Cannot set metadata when locked";
return false;
}
if (get_camera_metadata_entry_count(metadata) == 0) {
LOGF(ERROR) << "The input metadata is empty";
return false;
}
metadata_.acquire(clone_camera_metadata(metadata));
return !metadata_.isEmpty();
}
android::CameraMetadata Camera3CaptureDescriptor::ReleaseMetadata() {
CHECK(!IsLocked());
android::CameraMetadata ret;
ret.acquire(metadata_.release());
return ret;
}
bool Camera3CaptureDescriptor::HasMetadata(uint32_t tag) const {
return metadata_.exists(tag);
}
void Camera3CaptureDescriptor::SetPartialResult(uint32_t partial_result) {
CHECK(!IsLocked());
partial_result_ = partial_result;
}
const Camera3StreamBuffer* Camera3CaptureDescriptor::GetInputBuffer() const {
if (input_buffer_) {
return &input_buffer_.value();
}
return nullptr;
}
std::optional<Camera3StreamBuffer>
Camera3CaptureDescriptor::AcquireInputBuffer() {
std::optional<Camera3StreamBuffer> ret = std::move(input_buffer_);
input_buffer_.reset();
return ret;
}
void Camera3CaptureDescriptor::SetInputBuffer(
Camera3StreamBuffer input_buffer) {
input_buffer.StartTracing(frame_number_);
input_buffer_ = std::move(input_buffer);
}
base::span<const Camera3StreamBuffer>
Camera3CaptureDescriptor::GetOutputBuffers() const {
return {output_buffers_.data(), output_buffers_.size()};
}
base::span<Camera3StreamBuffer>
Camera3CaptureDescriptor::GetMutableOutputBuffers() {
return {output_buffers_.data(), output_buffers_.size()};
}
std::vector<Camera3StreamBuffer>
Camera3CaptureDescriptor::AcquireOutputBuffers() {
return std::move(output_buffers_);
}
void Camera3CaptureDescriptor::SetOutputBuffers(
std::vector<Camera3StreamBuffer> output_buffers) {
for (auto& b : output_buffers) {
b.StartTracing(frame_number_);
}
output_buffers_ = std::move(output_buffers);
}
void Camera3CaptureDescriptor::AppendOutputBuffer(Camera3StreamBuffer buffer) {
buffer.StartTracing(frame_number_);
output_buffers_.push_back(std::move(buffer));
}
const camera3_capture_request* Camera3CaptureDescriptor::LockForRequest() {
if (type_ != Type::kCaptureRequest) {
LOGF(ERROR) << "Cannot lock for capture request";
return nullptr;
}
CHECK(!IsLocked());
raw_descriptor_ = RawDescriptor();
raw_descriptor_->raw_request.frame_number = frame_number_;
raw_descriptor_->raw_request.settings = metadata_.getAndLock();
raw_descriptor_->raw_request.input_buffer =
input_buffer_ ? &input_buffer_->mutable_raw_buffer() : nullptr;
raw_descriptor_->raw_request.num_output_buffers = output_buffers_.size();
raw_output_buffers_.resize(output_buffers_.size());
for (int i = 0; i < output_buffers_.size(); ++i) {
output_buffers_[i].LockAndFill(&raw_output_buffers_[i]);
}
raw_descriptor_->raw_request.output_buffers = raw_output_buffers_.data();
raw_descriptor_->raw_request.num_physcam_settings = num_physcam_metadata_;
raw_descriptor_->raw_request.physcam_id = physcam_ids_;
raw_descriptor_->raw_request.physcam_settings = physcam_metadata_;
return &raw_descriptor_->raw_request;
}
const camera3_capture_result_t* Camera3CaptureDescriptor::LockForResult() {
if (type_ != Type::kCaptureResult) {
LOGF(ERROR) << "Cannot lock for capture result";
return nullptr;
}
CHECK(!IsLocked());
raw_descriptor_ = RawDescriptor();
raw_descriptor_->raw_result.frame_number = frame_number_;
raw_descriptor_->raw_result.result = metadata_.getAndLock();
raw_descriptor_->raw_result.num_output_buffers = output_buffers_.size();
raw_output_buffers_.resize(output_buffers_.size());
for (int i = 0; i < output_buffers_.size(); ++i) {
output_buffers_[i].LockAndFill(&raw_output_buffers_[i]);
}
raw_descriptor_->raw_result.output_buffers = raw_output_buffers_.data();
raw_descriptor_->raw_result.input_buffer =
input_buffer_ ? &input_buffer_->mutable_raw_buffer() : nullptr;
raw_descriptor_->raw_result.partial_result = partial_result_;
raw_descriptor_->raw_result.num_physcam_metadata = num_physcam_metadata_;
raw_descriptor_->raw_result.physcam_ids = physcam_ids_;
raw_descriptor_->raw_result.physcam_metadata = physcam_metadata_;
return &raw_descriptor_->raw_result;
}
const camera3_capture_request_t* Camera3CaptureDescriptor::GetLockedRequest() {
if (type_ != Type::kCaptureRequest) {
LOGF(ERROR) << "Cannot lock for capture request";
return nullptr;
}
if (!IsLocked()) {
return nullptr;
}
return &raw_descriptor_->raw_request;
}
const camera3_capture_result_t* Camera3CaptureDescriptor::GetLockedResult() {
if (type_ != Type::kCaptureResult) {
LOGF(ERROR) << "Cannot lock for capture result";
return nullptr;
}
if (!IsLocked()) {
return nullptr;
}
return &raw_descriptor_->raw_result;
}
void Camera3CaptureDescriptor::Unlock() {
if (!is_valid() || !IsLocked()) {
return;
}
switch (type_) {
case Type::kCaptureRequest:
metadata_.unlock(raw_descriptor_->raw_request.settings);
break;
case Type::kCaptureResult:
metadata_.unlock(raw_descriptor_->raw_result.result);
break;
case Type::kInvalidType:
NOTREACHED() << "Cannot unlock invalid descriptor";
}
for (auto& b : output_buffers_) {
b.Unlock();
}
raw_descriptor_.reset();
}
std::string Camera3CaptureDescriptor::ToJsonString() const {
if (!is_valid()) {
return std::string();
}
base::Value::Dict val;
val.Set("capture_type",
type_ == Type::kCaptureRequest ? "Request" : "Result");
val.Set("frame_number", base::checked_cast<int>(frame_number_));
if (input_buffer_) {
val.Set("input_buffer", ToValueDict(input_buffer_.value()));
}
base::Value::List out_bufs;
for (const auto& b : GetOutputBuffers()) {
out_bufs.Append(ToValueDict(b));
}
val.Set("output_buffers", std::move(out_bufs));
if (type_ == Type::kCaptureResult) {
val.Set("partial_result", base::checked_cast<int>(partial_result_));
}
std::string json_string;
if (!base::JSONWriter::WriteWithOptions(
val, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json_string)) {
LOGF(ERROR) << "Cannot convert capture descriptor to JSON string";
return std::string();
}
return json_string;
}
void Camera3CaptureDescriptor::PopulateEventAnnotation(
perfetto::EventContext& ctx) const {
if (!is_valid()) {
return;
}
ctx.AddDebugAnnotation("capture_type",
type_ == Type::kCaptureRequest ? "Request" : "Result");
ctx.AddDebugAnnotation("frame_number",
base::checked_cast<int>(frame_number_));
std::string input_buffer;
if (input_buffer_) {
perfetto::Flow::ProcessScoped(input_buffer_->flow_id())(ctx);
if (base::JSONWriter::WriteWithOptions(
ToValueDict(input_buffer_.value()),
base::JSONWriter::OPTIONS_PRETTY_PRINT, &input_buffer)) {
ctx.AddDebugAnnotation("input_buffer", input_buffer);
}
}
base::Value::List out_bufs;
for (const auto& b : GetOutputBuffers()) {
if (b.is_valid()) {
perfetto::Flow::ProcessScoped(b.flow_id())(ctx);
}
out_bufs.Append(ToValueDict(b));
}
std::string output_buffers;
if (base::JSONWriter::WriteWithOptions(
out_bufs, base::JSONWriter::OPTIONS_PRETTY_PRINT, &output_buffers)) {
ctx.AddDebugAnnotation("output_buffers", output_buffers);
}
if (type_ == Type::kCaptureResult) {
ctx.AddDebugAnnotation("partial_result",
base::checked_cast<int>(partial_result_));
}
}
void Camera3CaptureDescriptor::Invalidate() {
type_ = Type::kInvalidType;
frame_number_ = 0;
metadata_.clear();
input_buffer_.reset();
output_buffers_.clear();
partial_result_ = 0;
num_physcam_metadata_ = 0;
physcam_ids_ = nullptr;
physcam_metadata_ = nullptr;
feature_metadata_ = {};
raw_descriptor_.reset();
}
bool Camera3CaptureDescriptor::IsLocked() const {
return raw_descriptor_.has_value();
}
} // namespace cros