blob: 73fd3c206c8d643f2949aa415666f8084ed19177 [file] [log] [blame]
/*
* Copyright 2016 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "hal_adapter/camera_device_adapter.h"
#include <set>
#include <utility>
#include <vector>
#include <base/bind.h>
#include <base/bind_helpers.h>
#include <base/logging.h>
#include "hal_adapter/camera3_callback_ops_delegate.h"
#include "hal_adapter/camera3_device_ops_delegate.h"
namespace arc {
CameraDeviceAdapter::CameraDeviceAdapter(camera3_device_t* camera_device)
: camera_device_(camera_device) {
VLOG(2) << "CameraDeviceAdapter::CameraDeviceAdapter: " << camera_device_;
device_ops_delegate_.reset(new Camera3DeviceOpsDelegate(this));
}
CameraDeviceAdapter::~CameraDeviceAdapter() {
VLOG(2) << "CameraDeviceAdapter::~CameraDeviceAdapter: " << camera_device_;
}
mojom::Camera3DeviceOpsPtr CameraDeviceAdapter::GetDeviceOpsPtr() {
return device_ops_delegate_->CreateInterfacePtr();
}
int CameraDeviceAdapter::Close() {
// Close the device.
return camera_device_->common.close(&camera_device_->common);
}
int32_t CameraDeviceAdapter::Initialize(
mojom::Camera3CallbackOpsPtr callback_ops) {
VLOG(2) << "CameraDeviceAdapter::Initialize";
callback_ops_delegate_.reset(
new Camera3CallbackOpsDelegate(this, callback_ops.PassInterface()));
return camera_device_->ops->initialize(camera_device_,
callback_ops_delegate_.get());
}
mojom::Camera3StreamConfigurationPtr CameraDeviceAdapter::ConfigureStreams(
mojom::Camera3StreamConfigurationPtr config) {
VLOG(2) << "CameraDeviceAdapter::ConfigureStreams";
base::AutoLock l(streams_lock_);
std::map<uint64_t, std::unique_ptr<camera3_stream_t>> new_streams;
for (const auto& s : config->streams) {
uint64_t id = s->id;
std::unique_ptr<camera3_stream_t>& stream = new_streams[id];
auto it = streams_.find(id);
if (it == streams_.end()) {
VLOG(2) << "Add new stream: " << id;
stream.reset(new camera3_stream_t);
} else {
VLOG(2) << "Update existing stream: " << id;
stream.swap(it->second);
}
stream->stream_type = s->stream_type;
stream->width = s->width;
stream->height = s->height;
stream->format = s->format;
stream->usage = s->usage;
stream->max_buffers = s->max_buffers;
stream->data_space = static_cast<android_dataspace_t>(s->data_space);
stream->rotation = s->rotation;
}
streams_.swap(new_streams);
camera3_stream_configuration_t stream_list;
stream_list.num_streams = config->num_streams;
stream_list.streams = new camera3_stream_t*[config->num_streams];
stream_list.operation_mode = config->operation_mode;
int i = 0;
for (auto it = streams_.begin(); it != streams_.end(); it++) {
stream_list.streams[i++] = it->second.get();
}
mojom::Camera3StreamConfigurationPtr updated_config =
mojom::Camera3StreamConfiguration::New();
updated_config->error =
camera_device_->ops->configure_streams(camera_device_, &stream_list);
delete[](stream_list.streams);
if (!updated_config->error) {
updated_config->num_streams = streams_.size();
for (const auto& s : streams_) {
mojom::Camera3StreamPtr ptr = mojom::Camera3Stream::New();
ptr->id = s.first;
// HAL should only change usage and max_buffers.
ptr->usage = s.second->usage;
ptr->max_buffers = s.second->max_buffers;
updated_config->streams.push_back(std::move(ptr));
}
}
return updated_config;
}
mojom::CameraMetadataPtr CameraDeviceAdapter::ConstructDefaultRequestSettings(
int32_t type) {
VLOG(2) << "CameraDeviceAdapter::ConstructDefaultRequestSettings";
const camera_metadata_t* metadata =
camera_device_->ops->construct_default_request_settings(camera_device_,
type);
mojom::CameraMetadataPtr settings = mojom::CameraMetadata::New();
if (!metadata) {
settings->set_none(true);
} else {
mojo::ScopedDataPipeProducerHandle producer_handle;
mojo::ScopedDataPipeConsumerHandle consumer_handle;
int ret = internal::SerializeCameraMetadata(&producer_handle,
&consumer_handle, metadata);
if (ret) {
settings->set_none(true);
} else {
settings->set_metadata_handle(std::move(consumer_handle));
}
}
return settings;
}
int32_t CameraDeviceAdapter::ProcessCaptureRequest(
mojom::Camera3CaptureRequestPtr request) {
VLOG(2) << "CameraDeviceAdapter::ProcessCaptureRequest";
camera3_capture_request_t req;
req.frame_number = request->frame_number;
internal::CameraMetadataUniquePtr settings;
if (request->settings->is_none()) {
req.settings = nullptr;
} else {
settings = internal::DeserializeCameraMetadata(
request->settings->get_metadata_handle().get());
if (!settings) {
return -EINVAL;
}
req.settings = settings.get();
}
// Deserialize input buffer.
std::unique_ptr<camera3_stream_buffer_t> input_buffer;
internal::NativeHandleUniquePtr input_native_handle;
if (request->input_buffer->is_none()) {
req.input_buffer = nullptr;
} else {
base::AutoLock l(streams_lock_);
mojom::Camera3StreamBufferPtr& in_buf_ptr =
request->input_buffer->get_input_buffer();
input_buffer.reset(new camera3_stream_buffer_t);
input_native_handle.reset(native_handle_create(
in_buf_ptr->buffer->num_fds, in_buf_ptr->buffer->num_ints));
buffer_handle_t input_buffer_handle = input_native_handle.get();
input_buffer->buffer = &input_buffer_handle;
internal::DeserializeStreamBuffer(in_buf_ptr, streams_, input_buffer.get());
req.input_buffer = input_buffer.get();
}
// Deserialize output buffers.
req.num_output_buffers = request->num_output_buffers;
std::vector<camera3_stream_buffer_t> output_buffers(
request->num_output_buffers);
std::vector<internal::NativeHandleUniquePtr> output_native_handles(
request->num_output_buffers);
std::vector<buffer_handle_t> output_buffer_handles(
request->num_output_buffers);
{
base::AutoLock l(streams_lock_);
for (unsigned int i = 0; i < request->num_output_buffers; ++i) {
mojom::Camera3StreamBufferPtr& out_buf_ptr =
request->output_buffers->get_output_buffers()[i];
output_native_handles.at(i).reset(native_handle_create(
out_buf_ptr->buffer->num_fds, out_buf_ptr->buffer->num_ints));
output_buffer_handles.at(i) = output_native_handles.at(i).get();
output_buffers.at(i).buffer =
const_cast<const native_handle_t**>(&output_buffer_handles.at(i));
internal::DeserializeStreamBuffer(out_buf_ptr, streams_,
&output_buffers.at(i));
}
req.output_buffers =
const_cast<const camera3_stream_buffer_t*>(output_buffers.data());
}
return camera_device_->ops->process_capture_request(camera_device_, &req);
}
void CameraDeviceAdapter::Dump(mojo::ScopedHandle fd) {
VLOG(2) << "CameraDeviceAdapter::Dump";
base::ScopedFD dump_fd(internal::UnwrapPlatformHandle(std::move(fd)));
camera_device_->ops->dump(camera_device_, dump_fd.get());
}
int32_t CameraDeviceAdapter::Flush() {
VLOG(2) << "CameraDeviceAdapter::Flush";
return camera_device_->ops->flush(camera_device_);
}
mojom::Camera3CaptureResultPtr CameraDeviceAdapter::ProcessCaptureResult(
const camera3_capture_result_t* result) {
mojom::Camera3CaptureResultPtr r = mojom::Camera3CaptureResult::New();
r->frame_number = result->frame_number;
mojom::CameraMetadataPtr metadata = mojom::CameraMetadata::New();
mojo::ScopedDataPipeProducerHandle producer_handle;
mojo::ScopedDataPipeConsumerHandle consumer_handle;
if (!result->result) {
metadata->set_none(true);
} else {
int ret = internal::SerializeCameraMetadata(
&producer_handle, &consumer_handle, result->result);
if (ret) {
metadata->set_none(true);
} else {
metadata->set_metadata_handle(std::move(consumer_handle));
}
}
r->result = std::move(metadata);
// num_output_buffers may be 0.
r->num_output_buffers = result->num_output_buffers;
// Serialize output buffers. This may be none as num_output_buffers may be 0.
mojom::Camera3CaptureOutputBuffersPtr output_buffers =
mojom::Camera3CaptureOutputBuffers::New();
if (!result->output_buffers) {
output_buffers->set_none(true);
} else {
base::AutoLock l(streams_lock_);
mojo::Array<mojom::Camera3StreamBufferPtr> output_buffers_array;
for (unsigned int i = 0; i < result->num_output_buffers; i++) {
mojom::Camera3StreamBufferPtr out_buf =
internal::SerializeStreamBuffer(result->output_buffers + i, streams_);
if (out_buf.is_null()) {
LOG(ERROR) << "Failed to serialize output stream buffer";
// TODO(jcliang): Handle error?
}
output_buffers_array.push_back(std::move(out_buf));
}
output_buffers->set_output_buffers(std::move(output_buffers_array));
}
r->output_buffers = std::move(output_buffers);
// Serialize input buffer.
mojom::Camera3CaptureInputBufferPtr input_buffer =
mojom::Camera3CaptureInputBuffer::New();
if (!result->input_buffer) {
input_buffer->set_none(true);
} else {
base::AutoLock l(streams_lock_);
input_buffer->set_input_buffer(
internal::SerializeStreamBuffer(result->input_buffer, streams_));
}
r->input_buffer = std::move(input_buffer);
r->partial_result = result->partial_result;
return r;
}
mojom::Camera3NotifyMsgPtr CameraDeviceAdapter::Notify(
const camera3_notify_msg_t* msg) {
// Fill in the data from msg...
mojom::Camera3NotifyMsgPtr m = mojom::Camera3NotifyMsg::New();
m->type = msg->type;
m->message = mojom::Camera3NotifyMsgMessage::New();
if (msg->type == CAMERA3_MSG_ERROR) {
mojom::Camera3ErrorMsgPtr error = mojom::Camera3ErrorMsg::New();
error->frame_number = msg->message.error.frame_number;
uint64_t stream_id = 0;
{
base::AutoLock l(streams_lock_);
for (const auto& s : streams_) {
if (s.second.get() == msg->message.error.error_stream) {
stream_id = s.first;
break;
}
}
}
error->error_stream_id = stream_id;
error->error_code = msg->message.error.error_code;
m->message->set_error(std::move(error));
} else if (msg->type == CAMERA3_MSG_SHUTTER) {
mojom::Camera3ShutterMsgPtr shutter = mojom::Camera3ShutterMsg::New();
shutter->frame_number = msg->message.shutter.frame_number;
shutter->timestamp = msg->message.shutter.timestamp;
m->message->set_shutter(std::move(shutter));
} else {
LOG(ERROR) << "Invalid notify message type: " << msg->type;
}
return m;
}
} // namespace arc