blob: 996367e73413dd45d674f72092224937bf1d4cf0 [file] [log] [blame]
/*
* Copyright (C) 2013-2017 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "Camera3HAL"
#include <mutex>
#include "Camera3HAL.h"
#include "ICameraHw.h"
#include "PerformanceTraces.h"
namespace cros {
namespace intel {
/******************************************************************************
* C DEVICE INTERFACE IMPLEMENTATION WRAPPER
*****************************************************************************/
//Common check before the function call
#define FUNCTION_PREPARED_RETURN \
if (!dev)\
return -EINVAL;\
Camera3HAL* camera_priv = (Camera3HAL*)(dev->priv);
static int
hal_dev_initialize(const struct camera3_device * dev,
const camera3_callback_ops_t *callback_ops)
{
PERFORMANCE_HAL_ATRACE();
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);
// As per interface requirement this call should not take longer than 10ms
HAL_KPI_TRACE_CALL(1,10000000);
FUNCTION_PREPARED_RETURN
return camera_priv->initialize(callback_ops);
}
static int
hal_dev_configure_streams(const struct camera3_device * dev,
camera3_stream_configuration_t *stream_list)
{
PERFORMANCE_HAL_ATRACE();
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);
// As per interface requirement this call should not take longer than 1s
HAL_KPI_TRACE_CALL(1,1000000000);
FUNCTION_PREPARED_RETURN
return camera_priv->configure_streams(stream_list);
}
static const camera_metadata_t*
hal_dev_construct_default_request_settings(const struct camera3_device * dev,
int type)
{
PERFORMANCE_HAL_ATRACE();
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);
// As per interface requirement this call should not take longer than 5ms
HAL_KPI_TRACE_CALL(1, 5000000);
if (!dev)
return nullptr;
Camera3HAL* camera_priv = (Camera3HAL*)(dev->priv);
return camera_priv->construct_default_request_settings(type);
}
static int
hal_dev_process_capture_request(const struct camera3_device * dev,
camera3_capture_request_t *request)
{
PERFORMANCE_HAL_ATRACE();
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);
/**
* As per interface requirement this call should not take longer than 4
* frame intervals. Here we choose that value to be 4 frame intervals at
* 30fps = 4 x 33.3 ms = 133 ms
*/
HAL_KPI_TRACE_CALL(2, 133000000);
FUNCTION_PREPARED_RETURN
return camera_priv->process_capture_request(request);
}
static void
hal_dev_dump(const struct camera3_device * dev, int fd)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);
// As per interface requirement this call should not take longer than 10ms
HAL_KPI_TRACE_CALL(1, 10000000);
if (!dev)
return;
Camera3HAL* camera_priv = (Camera3HAL*)(dev->priv);
camera_priv->dump(fd);
}
static int
hal_dev_flush(const struct camera3_device * dev)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);
// As per interface requirement this call should not take longer than 1000ms
HAL_KPI_TRACE_CALL(1, 1000000000);
if (!dev)
return -EINVAL;
Camera3HAL* camera_priv = (Camera3HAL*)(dev->priv);
return camera_priv->flush();
}
static camera3_device_ops hal_dev_ops = {
NAMED_FIELD_INITIALIZER(initialize) hal_dev_initialize,
NAMED_FIELD_INITIALIZER(configure_streams) hal_dev_configure_streams,
NAMED_FIELD_INITIALIZER(register_stream_buffers) nullptr,
NAMED_FIELD_INITIALIZER(construct_default_request_settings) hal_dev_construct_default_request_settings,
NAMED_FIELD_INITIALIZER(process_capture_request) hal_dev_process_capture_request,
NAMED_FIELD_INITIALIZER(get_metadata_vendor_tag_ops) nullptr,
NAMED_FIELD_INITIALIZER(dump) hal_dev_dump,
NAMED_FIELD_INITIALIZER(flush) hal_dev_flush,
NAMED_FIELD_INITIALIZER(reserved) {0},
};
/******************************************************************************
* C++ CLASS IMPLEMENTATION
*****************************************************************************/
Camera3HAL::Camera3HAL(int cameraId, const hw_module_t* module) :
mCameraId(cameraId),
mCameraHw(nullptr),
mRequestThread(nullptr)
{
LOG1("@%s", __FUNCTION__);
struct camera_info info;
PlatformData::getCameraInfo(cameraId, &info);
CLEAR(mDevice);
mDevice.common.tag = HARDWARE_DEVICE_TAG;
mDevice.common.version = info.device_version;
mDevice.common.module = (hw_module_t *)(module);
// hal_dev_close is kept in the module for symmetry with dev_open
// it will be set there
mDevice.common.close = nullptr;
mDevice.ops = &hal_dev_ops;
mDevice.priv = this;
}
Camera3HAL::~Camera3HAL()
{
mDevice.priv = nullptr;
}
status_t Camera3HAL::init(void)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);
status_t status = UNKNOWN_ERROR;
mCameraHw = ICameraHw::createCameraHW(mCameraId);
status = mCameraHw->init();
if (status != NO_ERROR) {
LOGE("Error initializing Camera HW");
goto bail;
}
mRequestThread = std::unique_ptr<RequestThread>(new RequestThread(mCameraId, mCameraHw));
return NO_ERROR;
bail:
deinit();
return status;
}
status_t Camera3HAL::deinit(void)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);
status_t status = NO_ERROR;
// flush request first
if (mRequestThread != nullptr)
status = mRequestThread->flush();
if (mRequestThread != nullptr) {
status |= mRequestThread->deinit();
mRequestThread.reset();
}
if (mCameraHw != nullptr) {
delete mCameraHw;
mCameraHw = nullptr;
}
return status;
}
/* *********************************************************************
* Camera3 device APIs
* ********************************************************************/
int Camera3HAL::initialize(const camera3_callback_ops_t *callback_ops)
{
status_t status = NO_ERROR;
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);
if (callback_ops == nullptr)
return -ENODEV;
status = mRequestThread->init(callback_ops);
if (status != NO_ERROR) {
LOGE("Error initializing Request Thread status = %d", status);
return -ENODEV;
}
return status;
}
int Camera3HAL::configure_streams(camera3_stream_configuration_t *stream_list)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);
if (!stream_list)
return -EINVAL;
if (!stream_list->streams || !stream_list->num_streams) {
LOGE("%s: Bad input! streams list ptr: %p, num %d", __FUNCTION__,
stream_list->streams, stream_list->num_streams);
return -EINVAL;
}
int num = stream_list->num_streams;
LOG2("@%s, line:%d, stream num:%d", __FUNCTION__, __LINE__, num);
while (num--) {
if (!stream_list->streams[num]){
LOGE("%s: Bad input! streams (%d) 's ptr: %p", __FUNCTION__,
num, stream_list->streams[num]);
return -EINVAL;
}
}
status_t status = mRequestThread->configureStreams(stream_list);
return (status == NO_ERROR) ? 0 : -EINVAL;
}
camera_metadata_t* Camera3HAL::construct_default_request_settings(int type)
{
LOG2("@%s, type:%d", __FUNCTION__, type);
camera_metadata_t * meta;
if (type < CAMERA3_TEMPLATE_PREVIEW || type >= CAMERA3_TEMPLATE_COUNT)
return nullptr;
status_t status = mRequestThread->constructDefaultRequest(type, &meta);
if (status != NO_ERROR)
return nullptr;
return meta;
}
int Camera3HAL::process_capture_request(camera3_capture_request_t *request)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL2, LOG_TAG);
if (request == nullptr) {
LOGE("%s: request is null!", __FUNCTION__);
return -EINVAL;
} else if (!request->num_output_buffers || request->output_buffers == nullptr) {
LOGE("%s: num_output_buffers %d, output_buffers %p", __FUNCTION__,
request->num_output_buffers, request->output_buffers);
return -EINVAL;
} else if (request->output_buffers->stream == nullptr) {
LOGE("%s: output_buffers->stream is null!", __FUNCTION__);
return -EINVAL;
} else if (request->output_buffers->stream->priv == nullptr) {
LOGE("%s: output_buffers->stream->priv is null!", __FUNCTION__);
return -EINVAL;
} else if (request->output_buffers->buffer == nullptr
|| *(request->output_buffers->buffer) == nullptr) {
LOGE("%s: output buffer is invalid", __FUNCTION__);
return -EINVAL;
}
status_t status = mRequestThread->processCaptureRequest(request);
if (status == NO_ERROR)
return NO_ERROR;
return (status == BAD_VALUE) ? -EINVAL : -ENODEV;
}
void Camera3HAL::dump(int fd)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);
if (mRequestThread != nullptr)
mRequestThread->dump(fd);
if (mCameraHw != nullptr)
mCameraHw->dump(fd);
}
int Camera3HAL::flush()
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1, LOG_TAG);
if (CC_LIKELY(mRequestThread != nullptr))
return mRequestThread->flush();
return -ENODEV;
}
//----------------------------------------------------------------------------
} /* namespace intel */
} /* namespace cros */