From b0be1039c136f85778dffaf761af3d09907e21aa Mon Sep 17 00:00:00 2001 From: Alex Ray Date: Tue, 28 May 2013 15:52:47 -0700 Subject: [PATCH] modules: camera: add get_camera_info support Basic static metadata statically constructed from preprocessor passes over an array of camera metadata tags. Change-Id: I16ea9f4d68120d5a0bc010a4a67b0cbcd761329e --- modules/camera/Android.mk | 1 + modules/camera/Camera.cpp | 160 +++++++++++++++++++++++++++++++++++++ modules/camera/Camera.h | 8 ++ modules/camera/CameraHAL.cpp | 4 +- modules/camera/Metadata.cpp | 184 +++++++++++++++++++++++++++++++++++++++++++ modules/camera/Metadata.h | 75 ++++++++++++++++++ 6 files changed, 430 insertions(+), 2 deletions(-) create mode 100644 modules/camera/Metadata.cpp create mode 100644 modules/camera/Metadata.h diff --git a/modules/camera/Android.mk b/modules/camera/Android.mk index 5d26934..e02a143 100644 --- a/modules/camera/Android.mk +++ b/modules/camera/Android.mk @@ -26,6 +26,7 @@ LOCAL_C_INCLUDES += \ LOCAL_SRC_FILES := \ CameraHAL.cpp \ Camera.cpp \ + Metadata.cpp \ Stream.cpp \ LOCAL_SHARED_LIBRARIES := \ diff --git a/modules/camera/Camera.cpp b/modules/camera/Camera.cpp index 718d42b..76fe1a0 100644 --- a/modules/camera/Camera.cpp +++ b/modules/camera/Camera.cpp @@ -19,7 +19,9 @@ #include #include #include +#include #include "CameraHAL.h" +#include "Metadata.h" #include "Stream.h" //#define LOG_NDEBUG 0 @@ -34,6 +36,8 @@ #define CAMERA_SYNC_TIMEOUT 5000 // in msecs +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) + namespace default_camera_hal { extern "C" { @@ -48,6 +52,7 @@ static int close_device(hw_device_t* dev) Camera::Camera(int id) : mId(id), + mStaticInfo(NULL), mBusy(false), mCallbackOps(NULL), mStreams(NULL), @@ -59,6 +64,7 @@ Camera::Camera(int id) memset(&mDevice, 0, sizeof(mDevice)); mDevice.common.tag = HARDWARE_DEVICE_TAG; + mDevice.common.version = CAMERA_DEVICE_API_VERSION_3_0; mDevice.common.close = close_device; mDevice.ops = const_cast(&sOps); mDevice.priv = this; @@ -88,6 +94,25 @@ int Camera::open(const hw_module_t *module, hw_device_t **device) return 0; } +int Camera::getInfo(struct camera_info *info) +{ + int ret = 0; + + info->facing = CAMERA_FACING_FRONT; + info->orientation = 0; + info->device_version = mDevice.common.version; + + pthread_mutex_lock(&mMutex); + if (mStaticInfo == NULL) { + ret = initStaticInfo(); + } + pthread_mutex_unlock(&mMutex); + + info->static_camera_characteristics = mStaticInfo; + + return ret; +} + int Camera::close() { ALOGI("%s:%d: Closing camera device", __func__, mId); @@ -113,6 +138,141 @@ int Camera::initialize(const camera3_callback_ops_t *callback_ops) return 0; } +int Camera::initStaticInfo() +{ + /* + * Setup static camera info. This will have to customized per camera + * device. + */ + + /* android.control */ + int32_t android_control_ae_available_target_fps_ranges[] = {30, 30}; + mMetadata.addInt32(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, + ARRAY_SIZE(android_control_ae_available_target_fps_ranges), + android_control_ae_available_target_fps_ranges); + + int32_t android_control_ae_compensation_range[] = {-4, 4}; + mMetadata.addInt32(ANDROID_CONTROL_AE_COMPENSATION_RANGE, + ARRAY_SIZE(android_control_ae_compensation_range), + android_control_ae_compensation_range); + + camera_metadata_rational_t android_control_ae_compensation_step[] = {{2,1}}; + mMetadata.addRational(ANDROID_CONTROL_AE_COMPENSATION_STEP, + ARRAY_SIZE(android_control_ae_compensation_step), + android_control_ae_compensation_step); + + int32_t android_control_max_regions[] = {1}; + mMetadata.addInt32(ANDROID_CONTROL_MAX_REGIONS, + ARRAY_SIZE(android_control_max_regions), + android_control_max_regions); + + /* android.jpeg */ + int32_t android_jpeg_available_thumbnail_sizes[] = {0, 0, 128, 96}; + mMetadata.addInt32(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, + ARRAY_SIZE(android_jpeg_available_thumbnail_sizes), + android_jpeg_available_thumbnail_sizes); + + /* android.lens */ + float android_lens_info_available_focal_lengths[] = {1.0}; + mMetadata.addFloat(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, + ARRAY_SIZE(android_lens_info_available_focal_lengths), + android_lens_info_available_focal_lengths); + + /* android.request */ + int32_t android_request_max_num_output_streams[] = {0, 3, 1}; + mMetadata.addInt32(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, + ARRAY_SIZE(android_request_max_num_output_streams), + android_request_max_num_output_streams); + + /* android.scaler */ + int32_t android_scaler_available_formats[] = { + HAL_PIXEL_FORMAT_RAW_SENSOR, + HAL_PIXEL_FORMAT_BLOB, + HAL_PIXEL_FORMAT_RGBA_8888, + HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, + // These are handled by YCbCr_420_888 + // HAL_PIXEL_FORMAT_YV12, + // HAL_PIXEL_FORMAT_YCrCb_420_SP, + HAL_PIXEL_FORMAT_YCbCr_420_888}; + mMetadata.addInt32(ANDROID_SCALER_AVAILABLE_FORMATS, + ARRAY_SIZE(android_scaler_available_formats), + android_scaler_available_formats); + + int64_t android_scaler_available_jpeg_min_durations[] = {1}; + mMetadata.addInt64(ANDROID_SCALER_AVAILABLE_JPEG_MIN_DURATIONS, + ARRAY_SIZE(android_scaler_available_jpeg_min_durations), + android_scaler_available_jpeg_min_durations); + + int32_t android_scaler_available_jpeg_sizes[] = {640, 480}; + mMetadata.addInt32(ANDROID_SCALER_AVAILABLE_JPEG_SIZES, + ARRAY_SIZE(android_scaler_available_jpeg_sizes), + android_scaler_available_jpeg_sizes); + + float android_scaler_available_max_digital_zoom[] = {1}; + mMetadata.addFloat(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, + ARRAY_SIZE(android_scaler_available_max_digital_zoom), + android_scaler_available_max_digital_zoom); + + int64_t android_scaler_available_processed_min_durations[] = {1}; + mMetadata.addInt64(ANDROID_SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS, + ARRAY_SIZE(android_scaler_available_processed_min_durations), + android_scaler_available_processed_min_durations); + + int32_t android_scaler_available_processed_sizes[] = {640, 480}; + mMetadata.addInt32(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES, + ARRAY_SIZE(android_scaler_available_processed_sizes), + android_scaler_available_processed_sizes); + + int64_t android_scaler_available_raw_min_durations[] = {1}; + mMetadata.addInt64(ANDROID_SCALER_AVAILABLE_RAW_MIN_DURATIONS, + ARRAY_SIZE(android_scaler_available_raw_min_durations), + android_scaler_available_raw_min_durations); + + int32_t android_scaler_available_raw_sizes[] = {640, 480}; + mMetadata.addInt32(ANDROID_SCALER_AVAILABLE_RAW_SIZES, + ARRAY_SIZE(android_scaler_available_raw_sizes), + android_scaler_available_raw_sizes); + + /* android.sensor */ + + int32_t android_sensor_info_active_array_size[] = {0, 0, 640, 480}; + mMetadata.addInt32(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, + ARRAY_SIZE(android_sensor_info_active_array_size), + android_sensor_info_active_array_size); + + int32_t android_sensor_info_available_sensitivities[] = + {100, 200, 400, 800, 1600}; + mMetadata.addInt32(ANDROID_SENSOR_INFO_AVAILABLE_SENSITIVITIES, + ARRAY_SIZE(android_sensor_info_available_sensitivities), + android_sensor_info_available_sensitivities); + + int64_t android_sensor_info_max_frame_duration[] = {30000000000}; + mMetadata.addInt64(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION, + ARRAY_SIZE(android_sensor_info_max_frame_duration), + android_sensor_info_max_frame_duration); + + float android_sensor_info_physical_size[] = {3.2, 2.4}; + mMetadata.addFloat(ANDROID_SENSOR_INFO_PHYSICAL_SIZE, + ARRAY_SIZE(android_sensor_info_physical_size), + android_sensor_info_physical_size); + + int32_t android_sensor_info_pixel_array_size[] = {640, 480}; + mMetadata.addInt32(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, + ARRAY_SIZE(android_sensor_info_pixel_array_size), + android_sensor_info_pixel_array_size); + + int32_t android_sensor_orientation[] = {0}; + mMetadata.addInt32(ANDROID_SENSOR_ORIENTATION, + ARRAY_SIZE(android_sensor_orientation), + android_sensor_orientation); + + /* End of static camera characteristics */ + + mStaticInfo = mMetadata.generate(); + + return 0; +} + int Camera::configureStreams(camera3_stream_configuration_t *stream_config) { camera3_stream_t *astream; diff --git a/modules/camera/Camera.h b/modules/camera/Camera.h index 4001453..e97dfd0 100644 --- a/modules/camera/Camera.h +++ b/modules/camera/Camera.h @@ -20,6 +20,7 @@ #include #include #include +#include "Metadata.h" #include "Stream.h" namespace default_camera_hal { @@ -36,6 +37,7 @@ class Camera { // Common Camera Device Operations (see ) int open(const hw_module_t *module, hw_device_t **device); + int getInfo(struct camera_info *info); int close(); // Camera v3 Device Operations (see ) @@ -51,6 +53,8 @@ class Camera { camera3_device_t mDevice; private: + // Separate initialization method for static metadata + int initStaticInfo(); // Reuse a stream already created by this device Stream *reuseStream(camera3_stream_t *astream); // Destroy all streams in a stream array, and the array itself @@ -71,6 +75,10 @@ class Camera { // Identifier used by framework to distinguish cameras const int mId; + // Metadata containing persistent camera characteristics + Metadata mMetadata; + // camera_metadata structure containing static characteristics + camera_metadata_t *mStaticInfo; // Busy flag indicates camera is in use bool mBusy; // Camera device operations handle shared by all devices diff --git a/modules/camera/CameraHAL.cpp b/modules/camera/CameraHAL.cpp index 05b1fad..0d8164c 100644 --- a/modules/camera/CameraHAL.cpp +++ b/modules/camera/CameraHAL.cpp @@ -76,7 +76,7 @@ int CameraHAL::getCameraInfo(int id, struct camera_info* info) return -ENODEV; } // TODO: return device-specific static metadata - return 0; + return mCameras[id]->getInfo(info); } int CameraHAL::setCallbacks(const camera_module_callbacks_t *callbacks) @@ -93,7 +93,7 @@ int CameraHAL::open(const hw_module_t* mod, const char* name, hw_device_t** dev) ALOGV("%s: module=%p, name=%s, device=%p", __func__, mod, name, dev); id = strtol(name, &nameEnd, 10); - if (nameEnd != NULL) { + if (*nameEnd != '\0') { ALOGE("%s: Invalid camera id name %s", __func__, name); return -EINVAL; } else if (id < 0 || id >= mNumberOfCameras) { diff --git a/modules/camera/Metadata.cpp b/modules/camera/Metadata.cpp new file mode 100644 index 0000000..77f5405 --- /dev/null +++ b/modules/camera/Metadata.cpp @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * 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. + */ + +#include +#include + +//#define LOG_NDEBUG 0 +#define LOG_TAG "Metadata" +#include + +#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL) +#include +#include "ScopedTrace.h" + +#include "Metadata.h" + +namespace default_camera_hal { + +Metadata::Metadata() + : mHead(NULL), + mTail(NULL), + mEntryCount(0), + mDataCount(0) +{ + // NULL (default) pthread mutex attributes + pthread_mutex_init(&mMutex, NULL); +} + +Metadata::~Metadata() +{ +} + +int Metadata::addUInt8(uint32_t tag, int count, uint8_t *data) +{ + if (!validate(tag, TYPE_BYTE, count)) return -EINVAL; + return add(tag, count, data); +} + +int Metadata::addInt32(uint32_t tag, int count, int32_t *data) +{ + if (!validate(tag, TYPE_INT32, count)) return -EINVAL; + return add(tag, count, data); +} + +int Metadata::addFloat(uint32_t tag, int count, float *data) +{ + if (!validate(tag, TYPE_FLOAT, count)) return -EINVAL; + return add(tag, count, data); +} + +int Metadata::addInt64(uint32_t tag, int count, int64_t *data) +{ + if (!validate(tag, TYPE_INT64, count)) return -EINVAL; + return add(tag, count, data); +} + +int Metadata::addDouble(uint32_t tag, int count, double *data) +{ + if (!validate(tag, TYPE_DOUBLE, count)) return -EINVAL; + return add(tag, count, data); +} + +int Metadata::addRational(uint32_t tag, int count, + camera_metadata_rational_t *data) +{ + if (!validate(tag, TYPE_RATIONAL, count)) return -EINVAL; + return add(tag, count, data); +} + +bool Metadata::validate(uint32_t tag, int tag_type, int count) +{ + if (get_camera_metadata_tag_type(tag) < 0) { + ALOGE("%s: Invalid metadata entry tag: %d", __func__, tag); + return false; + } + if (tag_type < 0 || tag_type >= NUM_TYPES) { + ALOGE("%s: Invalid metadata entry tag type: %d", __func__, tag_type); + return false; + } + if (tag_type != get_camera_metadata_tag_type(tag)) { + ALOGE("%s: Tag %d called with incorrect type: %s(%d)", __func__, tag, + camera_metadata_type_names[tag_type], tag_type); + return false; + } + if (count < 1) { + ALOGE("%s: Invalid metadata entry count: %d", __func__, count); + return false; + } + return true; +} + +int Metadata::add(uint32_t tag, int count, void *tag_data) +{ + int tag_type = get_camera_metadata_tag_type(tag); + size_t type_sz = camera_metadata_type_size[tag_type]; + + // Allocate array to hold new metadata + void *data = malloc(count * type_sz); + if (data == NULL) + return -ENOMEM; + memcpy(data, tag_data, count * type_sz); + + mEntryCount++; + mDataCount += calculate_camera_metadata_entry_data_size(tag_type, count); + push(new Entry(tag, data, count)); + return 0; +} + +camera_metadata_t* Metadata::generate() +{ + Entry *current = mHead; + + pthread_mutex_lock(&mMutex); + if (mGenerated == NULL) { + ALOGV("Generating new camera metadata structure"); + mGenerated = allocate_camera_metadata(mEntryCount, mDataCount); + if (mGenerated == NULL) { + ALOGE("%s: Failed to allocate metadata (%d entries %d data)", + __func__, mEntryCount, mDataCount); + } + } + // Walk list of entries adding each one to newly allocated metadata + while (current != NULL) { + add_camera_metadata_entry(mGenerated, current->mTag, current->mData, + current->mCount); + current = current->mNext; + } + pthread_mutex_unlock(&mMutex); + + return mGenerated; +} + +Metadata::Entry::Entry(uint32_t tag, void *data, int count) + : mNext(NULL), + mPrev(NULL), + mTag(tag), + mData(data), + mCount(count) +{ +} + +void Metadata::push(Entry *e) +{ + if (mHead == NULL) { + mHead = mTail = e; + } else { + mTail->insertAfter(e); + mTail = e; + } +} + +Metadata::Entry::~Entry() +{ + if (mNext != NULL) + mNext->mPrev = mPrev; + if (mPrev != NULL) + mPrev->mNext = mNext; +} + +void Metadata::Entry::insertAfter(Entry *e) +{ + if (e == NULL) + return; + if (mNext != NULL) + mNext->mPrev = e; + e->mNext = mNext; + e->mPrev = this; + mNext = e; +} + +} // namespace default_camera_hal diff --git a/modules/camera/Metadata.h b/modules/camera/Metadata.h new file mode 100644 index 0000000..d5aac36 --- /dev/null +++ b/modules/camera/Metadata.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * 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. + */ + +#ifndef METADATA_H_ +#define METADATA_H_ + +#include +#include +#include +#include + +namespace default_camera_hal { +// Metadata is a convenience class for dealing with libcamera_metadata +class Metadata { + public: + Metadata(); + ~Metadata(); + + // Parse and add an entry + int addUInt8(uint32_t tag, int count, uint8_t *data); + int addInt32(uint32_t tag, int count, int32_t *data); + int addFloat(uint32_t tag, int count, float *data); + int addInt64(uint32_t tag, int count, int64_t *data); + int addDouble(uint32_t tag, int count, double *data); + int addRational(uint32_t tag, int count, + camera_metadata_rational_t *data); + // Generate a camera_metadata structure and fill it with internal data + camera_metadata_t *generate(); + + private: + // Validate the tag, type and count for a metadata entry + bool validate(uint32_t tag, int tag_type, int count); + // Add a verified tag with data to this Metadata structure + int add(uint32_t tag, int count, void *tag_data); + + class Entry { + public: + Entry(uint32_t tag, void *data, int count); + ~Entry(); + Entry *mNext; + Entry *mPrev; + const uint32_t mTag; + const void *mData; + const int mCount; + void insertAfter(Entry *e); + }; + // List ends + Entry *mHead; + Entry *mTail; + // Append entry to list + void push(Entry *e); + // Total of entries and entry data size + int mEntryCount; + int mDataCount; + // Save generated metadata, invalidated on update + camera_metadata_t *mGenerated; + // Lock protecting the Metadata object for modifications + pthread_mutex_t mMutex; +}; +} // namespace default_camera_hal + +#endif // METADATA_H_ -- 2.11.0