diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2013-11-22 10:35:26 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2013-11-22 10:35:26 -0800 |
commit | bae5cf92cfa9e2867af91057265df7f029f7865e (patch) | |
tree | 36c850418ad1433bef13b30be214f4f844a14efa /modules | |
parent | af822c43cf144a991db49d8c25068d054265ae37 (diff) | |
parent | c9940a2bfe94dbe2ef3bfe5e8692bf4e3cea5ba0 (diff) | |
download | hardware_libhardware-bae5cf92cfa9e2867af91057265df7f029f7865e.zip hardware_libhardware-bae5cf92cfa9e2867af91057265df7f029f7865e.tar.gz hardware_libhardware-bae5cf92cfa9e2867af91057265df7f029f7865e.tar.bz2 |
Merge commit 'c9940a2bfe94dbe2ef3bfe5e8692bf4e3cea5ba0' into HEAD
Diffstat (limited to 'modules')
-rw-r--r-- | modules/Android.mk | 3 | ||||
-rw-r--r-- | modules/audio/audio_policy.c | 11 | ||||
-rw-r--r--[-rwxr-xr-x] | modules/audio_remote_submix/audio_hw.cpp | 8 | ||||
-rw-r--r-- | modules/camera/Android.mk | 3 | ||||
-rw-r--r-- | modules/camera/Camera.cpp | 528 | ||||
-rw-r--r-- | modules/camera/Camera.h | 40 | ||||
-rw-r--r-- | modules/camera/CameraHAL.cpp | 9 | ||||
-rw-r--r-- | modules/camera/Metadata.cpp | 246 | ||||
-rw-r--r-- | modules/camera/Metadata.h | 79 | ||||
-rw-r--r-- | modules/camera/ScopedTrace.h | 51 | ||||
-rw-r--r-- | modules/camera/Stream.cpp | 177 | ||||
-rw-r--r-- | modules/camera/Stream.h | 79 | ||||
-rw-r--r-- | modules/consumerir/Android.mk | 25 | ||||
-rw-r--r-- | modules/consumerir/consumerir.c | 116 | ||||
-rw-r--r-- | modules/gralloc/gralloc.cpp | 2 |
15 files changed, 1345 insertions, 32 deletions
diff --git a/modules/Android.mk b/modules/Android.mk index 486b42d..b2d5a2a 100644 --- a/modules/Android.mk +++ b/modules/Android.mk @@ -1,2 +1,3 @@ -hardware_modules := gralloc hwcomposer audio nfc nfc-nci local_time power usbaudio audio_remote_submix camera +hardware_modules := gralloc hwcomposer audio nfc nfc-nci local_time \ + power usbaudio audio_remote_submix camera consumerir include $(call all-named-subdir-makefiles,$(hardware_modules)) diff --git a/modules/audio/audio_policy.c b/modules/audio/audio_policy.c index 2dd3dbe..9335654 100644 --- a/modules/audio/audio_policy.c +++ b/modules/audio/audio_policy.c @@ -99,7 +99,8 @@ static audio_io_handle_t ap_get_output(struct audio_policy *pol, uint32_t sampling_rate, audio_format_t format, audio_channel_mask_t channelMask, - audio_output_flags_t flags) + audio_output_flags_t flags, + const audio_offload_info_t *info) { return 0; } @@ -229,6 +230,12 @@ static int ap_dump(const struct audio_policy *pol, int fd) return -ENOSYS; } +static bool ap_is_offload_supported(const struct audio_policy *pol, + const audio_offload_info_t *info) +{ + return false; +} + static int create_default_ap(const struct audio_policy_device *device, struct audio_policy_service_ops *aps_ops, void *service, @@ -278,6 +285,8 @@ static int create_default_ap(const struct audio_policy_device *device, dap->policy.is_stream_active = ap_is_stream_active; dap->policy.dump = ap_dump; + dap->policy.is_offload_supported = ap_is_offload_supported; + dap->service = service; dap->aps_ops = aps_ops; diff --git a/modules/audio_remote_submix/audio_hw.cpp b/modules/audio_remote_submix/audio_hw.cpp index 5e88ef7..9df17b6 100755..100644 --- a/modules/audio_remote_submix/audio_hw.cpp +++ b/modules/audio_remote_submix/audio_hw.cpp @@ -271,7 +271,7 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, return 0; } else { // write() returned UNDERRUN or WOULD_BLOCK, retry - ALOGE("out_write() write to pipe returned unexpected %16lx", written_frames); + ALOGE("out_write() write to pipe returned unexpected %d", written_frames); written_frames = sink->write(buffer, frames); } } @@ -281,7 +281,7 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, pthread_mutex_unlock(&out->dev->lock); if (written_frames < 0) { - ALOGE("out_write() failed writing to pipe with %16lx", written_frames); + ALOGE("out_write() failed writing to pipe with %d", written_frames); return 0; } else { ALOGV("out_write() wrote %lu bytes)", written_frames * frame_size); @@ -549,7 +549,7 @@ static int adev_open_output_stream(struct audio_hw_device *dev, config->channel_mask = AUDIO_CHANNEL_OUT_STEREO; rsxadev->config.channel_mask = config->channel_mask; - if ((config->sample_rate != 48000) || (config->sample_rate != 44100)) { + if ((config->sample_rate != 48000) && (config->sample_rate != 44100)) { config->sample_rate = DEFAULT_RATE_HZ; } rsxadev->config.rate = config->sample_rate; @@ -708,7 +708,7 @@ static int adev_open_input_stream(struct audio_hw_device *dev, config->channel_mask = AUDIO_CHANNEL_IN_STEREO; rsxadev->config.channel_mask = config->channel_mask; - if ((config->sample_rate != 48000) || (config->sample_rate != 44100)) { + if ((config->sample_rate != 48000) && (config->sample_rate != 44100)) { config->sample_rate = DEFAULT_RATE_HZ; } rsxadev->config.rate = config->sample_rate; diff --git a/modules/camera/Android.mk b/modules/camera/Android.mk index eebffc1..e02a143 100644 --- a/modules/camera/Android.mk +++ b/modules/camera/Android.mk @@ -26,11 +26,14 @@ LOCAL_C_INCLUDES += \ LOCAL_SRC_FILES := \ CameraHAL.cpp \ Camera.cpp \ + Metadata.cpp \ + Stream.cpp \ LOCAL_SHARED_LIBRARIES := \ libcamera_metadata \ libcutils \ liblog \ + libsync \ LOCAL_CFLAGS += -Wall -Wextra -fvisibility=hidden diff --git a/modules/camera/Camera.cpp b/modules/camera/Camera.cpp index 203b772..973380e 100644 --- a/modules/camera/Camera.cpp +++ b/modules/camera/Camera.cpp @@ -17,7 +17,12 @@ #include <cstdlib> #include <pthread.h> #include <hardware/camera3.h> +#include <sync/sync.h> +#include <system/camera_metadata.h> +#include <system/graphics.h> #include "CameraHAL.h" +#include "Metadata.h" +#include "Stream.h" //#define LOG_NDEBUG 0 #define LOG_TAG "Camera" @@ -25,9 +30,14 @@ #define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL) #include <cutils/trace.h> +#include "ScopedTrace.h" #include "Camera.h" +#define CAMERA_SYNC_TIMEOUT 5000 // in msecs + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) + namespace default_camera_hal { extern "C" { @@ -42,14 +52,19 @@ static int close_device(hw_device_t* dev) Camera::Camera(int id) : mId(id), + mStaticInfo(NULL), mBusy(false), - mCallbackOps(NULL) + mCallbackOps(NULL), + mStreams(NULL), + mNumStreams(0), + mSettings(NULL) { - pthread_mutex_init(&mMutex, - NULL); // No pthread mutex attributes. + pthread_mutex_init(&mMutex, NULL); + pthread_mutex_init(&mStaticInfoMutex, NULL); 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<camera3_device_ops_t*>(&sOps); mDevice.priv = this; @@ -57,16 +72,17 @@ Camera::Camera(int id) Camera::~Camera() { + pthread_mutex_destroy(&mMutex); + pthread_mutex_destroy(&mStaticInfoMutex); } int Camera::open(const hw_module_t *module, hw_device_t **device) { ALOGI("%s:%d: Opening camera device", __func__, mId); - ATRACE_BEGIN(__func__); + CAMTRACE_CALL(); pthread_mutex_lock(&mMutex); if (mBusy) { pthread_mutex_unlock(&mMutex); - ATRACE_END(); ALOGE("%s:%d: Error! Camera device already opened", __func__, mId); return -EBUSY; } @@ -77,18 +93,33 @@ int Camera::open(const hw_module_t *module, hw_device_t **device) *device = &mDevice.common; pthread_mutex_unlock(&mMutex); - ATRACE_END(); + return 0; +} + +int Camera::getInfo(struct camera_info *info) +{ + info->facing = CAMERA_FACING_FRONT; + info->orientation = 0; + info->device_version = mDevice.common.version; + + pthread_mutex_lock(&mStaticInfoMutex); + if (mStaticInfo == NULL) { + mStaticInfo = initStaticInfo(); + } + pthread_mutex_unlock(&mStaticInfoMutex); + + info->static_camera_characteristics = mStaticInfo; + return 0; } int Camera::close() { ALOGI("%s:%d: Closing camera device", __func__, mId); - ATRACE_BEGIN(__func__); + CAMTRACE_CALL(); pthread_mutex_lock(&mMutex); if (!mBusy) { pthread_mutex_unlock(&mMutex); - ATRACE_END(); ALOGE("%s:%d: Error! Camera device not open", __func__, mId); return -EINVAL; } @@ -97,7 +128,6 @@ int Camera::close() mBusy = false; pthread_mutex_unlock(&mMutex); - ATRACE_END(); return 0; } @@ -105,44 +135,500 @@ int Camera::initialize(const camera3_callback_ops_t *callback_ops) { ALOGV("%s:%d: callback_ops=%p", __func__, mId, callback_ops); mCallbackOps = callback_ops; + // Create standard settings templates + // 0 is invalid as template + mTemplates[0] = NULL; + // CAMERA3_TEMPLATE_PREVIEW = 1 + mTemplates[1] = new Metadata(ANDROID_CONTROL_MODE_OFF, + ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW); + // CAMERA3_TEMPLATE_STILL_CAPTURE = 2 + mTemplates[2] = new Metadata(ANDROID_CONTROL_MODE_OFF, + ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE); + // CAMERA3_TEMPLATE_VIDEO_RECORD = 3 + mTemplates[3] = new Metadata(ANDROID_CONTROL_MODE_OFF, + ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD); + // CAMERA3_TEMPLATE_VIDEO_SNAPSHOT = 4 + mTemplates[4] = new Metadata(ANDROID_CONTROL_MODE_OFF, + ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT); + // CAMERA3_TEMPLATE_STILL_ZERO_SHUTTER_LAG = 5 + mTemplates[5] = new Metadata(ANDROID_CONTROL_MODE_OFF, + ANDROID_CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG); + // Pre-generate metadata structures + for (int i = 1; i < CAMERA3_TEMPLATE_COUNT; i++) { + mTemplates[i]->generate(); + } + // TODO: create vendor templates return 0; } -int Camera::configureStreams(camera3_stream_configuration_t *stream_list) +camera_metadata_t *Camera::initStaticInfo() +{ + /* + * Setup static camera info. This will have to customized per camera + * device. + */ + Metadata m; + + /* android.control */ + int32_t android_control_ae_available_target_fps_ranges[] = {30, 30}; + m.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}; + m.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}}; + m.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}; + m.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}; + m.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}; + m.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}; + m.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}; + m.addInt32(ANDROID_SCALER_AVAILABLE_FORMATS, + ARRAY_SIZE(android_scaler_available_formats), + android_scaler_available_formats); + + int64_t android_scaler_available_jpeg_min_durations[] = {1}; + m.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}; + m.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}; + m.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}; + m.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}; + m.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}; + m.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}; + m.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}; + m.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_sensitivity_range[] = + {100, 1600}; + m.addInt32(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE, + ARRAY_SIZE(android_sensor_info_sensitivity_range), + android_sensor_info_sensitivity_range); + + int64_t android_sensor_info_max_frame_duration[] = {30000000000}; + m.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}; + m.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}; + m.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}; + m.addInt32(ANDROID_SENSOR_ORIENTATION, + ARRAY_SIZE(android_sensor_orientation), + android_sensor_orientation); + + /* End of static camera characteristics */ + + return clone_camera_metadata(m.generate()); +} + +int Camera::configureStreams(camera3_stream_configuration_t *stream_config) { - ALOGV("%s:%d: stream_list=%p", __func__, mId, stream_list); - // TODO: validate input, create internal stream representations + camera3_stream_t *astream; + Stream **newStreams = NULL; + + CAMTRACE_CALL(); + ALOGV("%s:%d: stream_config=%p", __func__, mId, stream_config); + + if (stream_config == NULL) { + ALOGE("%s:%d: NULL stream configuration array", __func__, mId); + return -EINVAL; + } + if (stream_config->num_streams == 0) { + ALOGE("%s:%d: Empty stream configuration array", __func__, mId); + return -EINVAL; + } + + // Create new stream array + newStreams = new Stream*[stream_config->num_streams]; + ALOGV("%s:%d: Number of Streams: %d", __func__, mId, + stream_config->num_streams); + + pthread_mutex_lock(&mMutex); + + // Mark all current streams unused for now + for (int i = 0; i < mNumStreams; i++) + mStreams[i]->mReuse = false; + // Fill new stream array with reused streams and new streams + for (unsigned int i = 0; i < stream_config->num_streams; i++) { + astream = stream_config->streams[i]; + if (astream->max_buffers > 0) { + ALOGV("%s:%d: Reusing stream %d", __func__, mId, i); + newStreams[i] = reuseStream(astream); + } else { + ALOGV("%s:%d: Creating new stream %d", __func__, mId, i); + newStreams[i] = new Stream(mId, astream); + } + + if (newStreams[i] == NULL) { + ALOGE("%s:%d: Error processing stream %d", __func__, mId, i); + goto err_out; + } + astream->priv = newStreams[i]; + } + + // Verify the set of streams in aggregate + if (!isValidStreamSet(newStreams, stream_config->num_streams)) { + ALOGE("%s:%d: Invalid stream set", __func__, mId); + goto err_out; + } + + // Set up all streams (calculate usage/max_buffers for each) + setupStreams(newStreams, stream_config->num_streams); + + // Destroy all old streams and replace stream array with new one + destroyStreams(mStreams, mNumStreams); + mStreams = newStreams; + mNumStreams = stream_config->num_streams; + + // Clear out last seen settings metadata + setSettings(NULL); + + pthread_mutex_unlock(&mMutex); return 0; + +err_out: + // Clean up temporary streams, preserve existing mStreams/mNumStreams + destroyStreams(newStreams, stream_config->num_streams); + pthread_mutex_unlock(&mMutex); + return -EINVAL; +} + +void Camera::destroyStreams(Stream **streams, int count) +{ + if (streams == NULL) + return; + for (int i = 0; i < count; i++) { + // Only destroy streams that weren't reused + if (streams[i] != NULL && !streams[i]->mReuse) + delete streams[i]; + } + delete [] streams; +} + +Stream *Camera::reuseStream(camera3_stream_t *astream) +{ + Stream *priv = reinterpret_cast<Stream*>(astream->priv); + // Verify the re-used stream's parameters match + if (!priv->isValidReuseStream(mId, astream)) { + ALOGE("%s:%d: Mismatched parameter in reused stream", __func__, mId); + return NULL; + } + // Mark stream to be reused + priv->mReuse = true; + return priv; +} + +bool Camera::isValidStreamSet(Stream **streams, int count) +{ + int inputs = 0; + int outputs = 0; + + if (streams == NULL) { + ALOGE("%s:%d: NULL stream configuration streams", __func__, mId); + return false; + } + if (count == 0) { + ALOGE("%s:%d: Zero count stream configuration streams", __func__, mId); + return false; + } + // Validate there is at most one input stream and at least one output stream + for (int i = 0; i < count; i++) { + // A stream may be both input and output (bidirectional) + if (streams[i]->isInputType()) + inputs++; + if (streams[i]->isOutputType()) + outputs++; + } + ALOGV("%s:%d: Configuring %d output streams and %d input streams", + __func__, mId, outputs, inputs); + if (outputs < 1) { + ALOGE("%s:%d: Stream config must have >= 1 output", __func__, mId); + return false; + } + if (inputs > 1) { + ALOGE("%s:%d: Stream config must have <= 1 input", __func__, mId); + return false; + } + // TODO: check for correct number of Bayer/YUV/JPEG/Encoder streams + return true; +} + +void Camera::setupStreams(Stream **streams, int count) +{ + /* + * This is where the HAL has to decide internally how to handle all of the + * streams, and then produce usage and max_buffer values for each stream. + * Note, the stream array has been checked before this point for ALL invalid + * conditions, so it must find a successful configuration for this stream + * array. The HAL may not return an error from this point. + * + * In this demo HAL, we just set all streams to be the same dummy values; + * real implementations will want to avoid USAGE_SW_{READ|WRITE}_OFTEN. + */ + for (int i = 0; i < count; i++) { + uint32_t usage = 0; + + if (streams[i]->isOutputType()) + usage |= GRALLOC_USAGE_SW_WRITE_OFTEN | + GRALLOC_USAGE_HW_CAMERA_WRITE; + if (streams[i]->isInputType()) + usage |= GRALLOC_USAGE_SW_READ_OFTEN | + GRALLOC_USAGE_HW_CAMERA_READ; + + streams[i]->setUsage(usage); + streams[i]->setMaxBuffers(1); + } } int Camera::registerStreamBuffers(const camera3_stream_buffer_set_t *buf_set) { ALOGV("%s:%d: buffer_set=%p", __func__, mId, buf_set); - // TODO: register buffers with hardware - return 0; + if (buf_set == NULL) { + ALOGE("%s:%d: NULL buffer set", __func__, mId); + return -EINVAL; + } + if (buf_set->stream == NULL) { + ALOGE("%s:%d: NULL stream handle", __func__, mId); + return -EINVAL; + } + Stream *stream = reinterpret_cast<Stream*>(buf_set->stream->priv); + return stream->registerBuffers(buf_set); } const camera_metadata_t* Camera::constructDefaultRequestSettings(int type) { ALOGV("%s:%d: type=%d", __func__, mId, type); - // TODO: return statically built default request - return NULL; + + if (type < 1 || type >= CAMERA3_TEMPLATE_COUNT) { + ALOGE("%s:%d: Invalid template request type: %d", __func__, mId, type); + return NULL; + } + return mTemplates[type]->generate(); } int Camera::processCaptureRequest(camera3_capture_request_t *request) { + camera3_capture_result result; + ALOGV("%s:%d: request=%p", __func__, mId, request); - ATRACE_BEGIN(__func__); + CAMTRACE_CALL(); if (request == NULL) { ALOGE("%s:%d: NULL request recieved", __func__, mId); - ATRACE_END(); return -EINVAL; } - // TODO: verify request; submit request to hardware - ATRACE_END(); + ALOGV("%s:%d: Request Frame:%d Settings:%p", __func__, mId, + request->frame_number, request->settings); + + // NULL indicates use last settings + if (request->settings == NULL) { + if (mSettings == NULL) { + ALOGE("%s:%d: NULL settings without previous set Frame:%d Req:%p", + __func__, mId, request->frame_number, request); + return -EINVAL; + } + } else { + setSettings(request->settings); + } + + if (request->input_buffer != NULL) { + ALOGV("%s:%d: Reprocessing input buffer %p", __func__, mId, + request->input_buffer); + + if (!isValidReprocessSettings(request->settings)) { + ALOGE("%s:%d: Invalid settings for reprocess request: %p", + __func__, mId, request->settings); + return -EINVAL; + } + } else { + ALOGV("%s:%d: Capturing new frame.", __func__, mId); + + if (!isValidCaptureSettings(request->settings)) { + ALOGE("%s:%d: Invalid settings for capture request: %p", + __func__, mId, request->settings); + return -EINVAL; + } + } + + if (request->num_output_buffers <= 0) { + ALOGE("%s:%d: Invalid number of output buffers: %d", __func__, mId, + request->num_output_buffers); + return -EINVAL; + } + result.num_output_buffers = request->num_output_buffers; + result.output_buffers = new camera3_stream_buffer_t[result.num_output_buffers]; + for (unsigned int i = 0; i < request->num_output_buffers; i++) { + int res = processCaptureBuffer(&request->output_buffers[i], + const_cast<camera3_stream_buffer_t*>(&result.output_buffers[i])); + if (res) + goto err_out; + } + + result.frame_number = request->frame_number; + // TODO: return actual captured/reprocessed settings + result.result = request->settings; + // TODO: asynchronously return results + notifyShutter(request->frame_number, 0); + mCallbackOps->process_capture_result(mCallbackOps, &result); + return 0; + +err_out: + delete [] result.output_buffers; + // TODO: this should probably be a total device failure; transient for now + return -EINVAL; +} + +void Camera::setSettings(const camera_metadata_t *new_settings) +{ + if (mSettings != NULL) { + free_camera_metadata(mSettings); + mSettings = NULL; + } + + if (new_settings != NULL) + mSettings = clone_camera_metadata(new_settings); +} + +bool Camera::isValidCaptureSettings(const camera_metadata_t* /*settings*/) +{ + // TODO: reject settings that cannot be captured + return true; +} + +bool Camera::isValidReprocessSettings(const camera_metadata_t* /*settings*/) +{ + // TODO: reject settings that cannot be reprocessed + // input buffers unimplemented, use this to reject reprocessing requests + ALOGE("%s:%d: Input buffer reprocessing not implemented", __func__, mId); + return false; +} + +int Camera::processCaptureBuffer(const camera3_stream_buffer_t *in, + camera3_stream_buffer_t *out) +{ + if (in->acquire_fence != -1) { + int res = sync_wait(in->acquire_fence, CAMERA_SYNC_TIMEOUT); + if (res == -ETIME) { + ALOGE("%s:%d: Timeout waiting on buffer acquire fence", + __func__, mId); + return res; + } else if (res) { + ALOGE("%s:%d: Error waiting on buffer acquire fence: %s(%d)", + __func__, mId, strerror(-res), res); + return res; + } + } + + out->stream = in->stream; + out->buffer = in->buffer; + out->status = CAMERA3_BUFFER_STATUS_OK; + // TODO: use driver-backed release fences + out->acquire_fence = -1; + out->release_fence = -1; + + // TODO: lock and software-paint buffer + return 0; +} + +void Camera::notifyShutter(uint32_t frame_number, uint64_t timestamp) +{ + int res; + struct timespec ts; + + // If timestamp is 0, get timestamp from right now instead + if (timestamp == 0) { + ALOGW("%s:%d: No timestamp provided, using CLOCK_BOOTTIME", + __func__, mId); + res = clock_gettime(CLOCK_BOOTTIME, &ts); + if (res == 0) { + timestamp = ts.tv_sec * 1000000000ULL + ts.tv_nsec; + } else { + ALOGE("%s:%d: No timestamp and failed to get CLOCK_BOOTTIME %s(%d)", + __func__, mId, strerror(errno), errno); + } + } + camera3_notify_msg_t m; + memset(&m, 0, sizeof(m)); + m.type = CAMERA3_MSG_SHUTTER; + m.message.shutter.frame_number = frame_number; + m.message.shutter.timestamp = timestamp; + mCallbackOps->notify(mCallbackOps, &m); } void Camera::getMetadataVendorTagOps(vendor_tag_query_ops_t *ops) @@ -153,7 +639,7 @@ void Camera::getMetadataVendorTagOps(vendor_tag_query_ops_t *ops) void Camera::dump(int fd) { - ALOGV("%s:%d: Dumping to fd %d", fd); + ALOGV("%s:%d: Dumping to fd %d", __func__, mId, fd); // TODO: dprintf all relevant state to fd } diff --git a/modules/camera/Camera.h b/modules/camera/Camera.h index f2ad093..be672f9 100644 --- a/modules/camera/Camera.h +++ b/modules/camera/Camera.h @@ -20,6 +20,8 @@ #include <pthread.h> #include <hardware/hardware.h> #include <hardware/camera3.h> +#include "Metadata.h" +#include "Stream.h" namespace default_camera_hal { // Camera represents a physical camera on a device. @@ -35,6 +37,7 @@ class Camera { // Common Camera Device Operations (see <hardware/camera_common.h>) int open(const hw_module_t *module, hw_device_t **device); + int getInfo(struct camera_info *info); int close(); // Camera v3 Device Operations (see <hardware/camera3.h>) @@ -50,8 +53,34 @@ class Camera { camera3_device_t mDevice; private: + // Separate initialization method for static metadata + camera_metadata_t *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 + void destroyStreams(Stream **array, int count); + // Verify a set of streams is valid in aggregate + bool isValidStreamSet(Stream **array, int count); + // Calculate usage and max_bufs of each stream + void setupStreams(Stream **array, int count); + // Copy new settings for re-use and clean up old settings. + void setSettings(const camera_metadata_t *new_settings); + // Verify settings are valid for a capture + bool isValidCaptureSettings(const camera_metadata_t *settings); + // Verify settings are valid for reprocessing an input buffer + bool isValidReprocessSettings(const camera_metadata_t *settings); + // Process an output buffer + int processCaptureBuffer(const camera3_stream_buffer_t *in, + camera3_stream_buffer_t *out); + // Send a shutter notify message with start of exposure time + void notifyShutter(uint32_t frame_number, uint64_t timestamp); + // 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 @@ -60,6 +89,17 @@ class Camera { const camera3_callback_ops_t *mCallbackOps; // Lock protecting the Camera object for modifications pthread_mutex_t mMutex; + // Lock protecting only static camera characteristics, which may + // be accessed without the camera device open + pthread_mutex_t mStaticInfoMutex; + // Array of handles to streams currently in use by the device + Stream **mStreams; + // Number of streams in mStreams + int mNumStreams; + // Static array of standard camera settings templates + Metadata *mTemplates[CAMERA3_TEMPLATE_COUNT]; + // Most recent request settings seen, memoized to be reused + camera_metadata_t *mSettings; }; } // namespace default_camera_hal diff --git a/modules/camera/CameraHAL.cpp b/modules/camera/CameraHAL.cpp index 6cae7d2..dfbbe4c 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) @@ -90,11 +90,14 @@ int CameraHAL::open(const hw_module_t* mod, const char* name, hw_device_t** dev) { int id; char *nameEnd; - Camera *cam; ALOGV("%s: module=%p, name=%s, device=%p", __func__, mod, name, dev); + if (*name == '\0') { + ALOGE("%s: Invalid camera id name is NULL", __func__); + return -EINVAL; + } 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..d5854f9 --- /dev/null +++ b/modules/camera/Metadata.cpp @@ -0,0 +1,246 @@ +/* + * 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 <pthread.h> +#include <system/camera_metadata.h> + +//#define LOG_NDEBUG 0 +#define LOG_TAG "Metadata" +#include <cutils/log.h> + +#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL) +#include <cutils/trace.h> +#include "ScopedTrace.h" + +#include "Metadata.h" + +namespace default_camera_hal { + +Metadata::Metadata() + : mHead(NULL), + mTail(NULL), + mEntryCount(0), + mDataCount(0), + mGenerated(NULL), + mDirty(true) +{ + // NULL (default) pthread mutex attributes + pthread_mutex_init(&mMutex, NULL); +} + +Metadata::~Metadata() +{ + Entry *current = mHead; + + while (current != NULL) { + Entry *tmp = current; + current = current->mNext; + delete tmp; + } + + if (mGenerated != NULL) + free_camera_metadata(mGenerated); + + pthread_mutex_destroy(&mMutex); +} + +Metadata::Metadata(uint8_t mode, uint8_t intent) + : mHead(NULL), + mTail(NULL), + mEntryCount(0), + mDataCount(0), + mGenerated(NULL), + mDirty(true) +{ + pthread_mutex_init(&mMutex, NULL); + + if (validate(ANDROID_CONTROL_MODE, TYPE_BYTE, 1)) { + int res = add(ANDROID_CONTROL_MODE, 1, &mode); + if (res != 0) { + ALOGE("%s: Unable to add mode to template!", __func__); + } + } else { + ALOGE("%s: Invalid mode constructing template!", __func__); + } + + if (validate(ANDROID_CONTROL_CAPTURE_INTENT, TYPE_BYTE, 1)) { + int res = add(ANDROID_CONTROL_CAPTURE_INTENT, 1, &intent); + if (res != 0) { + ALOGE("%s: Unable to add capture intent to template!", __func__); + } + } else { + ALOGE("%s: Invalid capture intent constructing template!", __func__); + } +} + +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); + + pthread_mutex_lock(&mMutex); + mEntryCount++; + mDataCount += calculate_camera_metadata_entry_data_size(tag_type, count); + push(new Entry(tag, data, count)); + mDirty = true; + pthread_mutex_unlock(&mMutex); + return 0; +} + +camera_metadata_t* Metadata::generate() +{ + pthread_mutex_lock(&mMutex); + // Reuse if old generated metadata still valid + if (!mDirty && mGenerated != NULL) { + ALOGV("%s: Reusing generated metadata at %p", __func__, mGenerated); + goto out; + } + // Destroy old metadata + if (mGenerated != NULL) { + ALOGV("%s: Freeing generated metadata at %p", __func__, mGenerated); + free_camera_metadata(mGenerated); + mGenerated = NULL; + } + // Generate new metadata structure + ALOGV("%s: Generating new camera metadata structure, Entries:%d Data:%d", + __func__, mEntryCount, mDataCount); + mGenerated = allocate_camera_metadata(mEntryCount, mDataCount); + if (mGenerated == NULL) { + ALOGE("%s: Failed to allocate metadata (%d entries %d data)", + __func__, mEntryCount, mDataCount); + goto out; + } + // Walk list of entries adding each one to newly allocated metadata + for (Entry *current = mHead; current != NULL; current = current->mNext) { + int res = add_camera_metadata_entry(mGenerated, current->mTag, + current->mData, current->mCount); + if (res != 0) { + ALOGE("%s: Failed to add camera metadata: %d", __func__, res); + free_camera_metadata(mGenerated); + mGenerated = NULL; + goto out; + } + } + +out: + 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..22d2f22 --- /dev/null +++ b/modules/camera/Metadata.h @@ -0,0 +1,79 @@ +/* + * 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 <hardware/camera3.h> +#include <hardware/gralloc.h> +#include <system/camera_metadata.h> +#include <system/graphics.h> + +namespace default_camera_hal { +// Metadata is a convenience class for dealing with libcamera_metadata +class Metadata { + public: + Metadata(); + ~Metadata(); + // Constructor used for request metadata templates + Metadata(uint8_t mode, uint8_t intent); + + // 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; + // Flag to force metadata regeneration + bool mDirty; + // Lock protecting the Metadata object for modifications + pthread_mutex_t mMutex; +}; +} // namespace default_camera_hal + +#endif // METADATA_H_ diff --git a/modules/camera/ScopedTrace.h b/modules/camera/ScopedTrace.h new file mode 100644 index 0000000..ed00570 --- /dev/null +++ b/modules/camera/ScopedTrace.h @@ -0,0 +1,51 @@ +/* + * 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 CAMERA_SCOPED_TRACE_H +#define CAMERA_SCOPED_TRACE_H + +#include <stdint.h> +#include <cutils/trace.h> + +// See <cutils/trace.h> for more tracing macros. + +// CAMTRACE_NAME traces the beginning and end of the current scope. To trace +// the correct start and end times this macro should be declared first in the +// scope body. +#define CAMTRACE_NAME(name) ScopedTrace ___tracer(ATRACE_TAG, name) +// CAMTRACE_CALL is an ATRACE_NAME that uses the current function name. +#define CAMTRACE_CALL() CAMTRACE_NAME(__FUNCTION__) + +namespace default_camera_hal { + +class ScopedTrace { +public: +inline ScopedTrace(uint64_t tag, const char* name) + : mTag(tag) { + atrace_begin(mTag,name); +} + +inline ~ScopedTrace() { + atrace_end(mTag); +} + +private: + uint64_t mTag; +}; + +}; // namespace default_camera_hal + +#endif // CAMERA_SCOPED_TRACE_H diff --git a/modules/camera/Stream.cpp b/modules/camera/Stream.cpp new file mode 100644 index 0000000..aae7adb --- /dev/null +++ b/modules/camera/Stream.cpp @@ -0,0 +1,177 @@ +/* + * 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 <pthread.h> +#include <hardware/camera3.h> +#include <hardware/gralloc.h> +#include <system/graphics.h> + +//#define LOG_NDEBUG 0 +#define LOG_TAG "Stream" +#include <cutils/log.h> + +#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL) +#include <cutils/trace.h> +#include "ScopedTrace.h" + +#include "Stream.h" + +namespace default_camera_hal { + +Stream::Stream(int id, camera3_stream_t *s) + : mReuse(false), + mId(id), + mStream(s), + mType(s->stream_type), + mWidth(s->width), + mHeight(s->height), + mFormat(s->format), + mUsage(0), + mMaxBuffers(0), + mRegistered(false), + mBuffers(0), + mNumBuffers(0) +{ + // NULL (default) pthread mutex attributes + pthread_mutex_init(&mMutex, NULL); +} + +Stream::~Stream() +{ + pthread_mutex_lock(&mMutex); + unregisterBuffers_L(); + pthread_mutex_unlock(&mMutex); +} + +void Stream::setUsage(uint32_t usage) +{ + pthread_mutex_lock(&mMutex); + if (usage != mUsage) { + mUsage = usage; + mStream->usage = usage; + unregisterBuffers_L(); + } + pthread_mutex_unlock(&mMutex); +} + +void Stream::setMaxBuffers(uint32_t max_buffers) +{ + pthread_mutex_lock(&mMutex); + if (max_buffers != mMaxBuffers) { + mMaxBuffers = max_buffers; + mStream->max_buffers = max_buffers; + unregisterBuffers_L(); + } + pthread_mutex_unlock(&mMutex); +} + +int Stream::getType() +{ + return mType; +} + +bool Stream::isInputType() +{ + return mType == CAMERA3_STREAM_INPUT || + mType == CAMERA3_STREAM_BIDIRECTIONAL; +} + +bool Stream::isOutputType() +{ + return mType == CAMERA3_STREAM_OUTPUT || + mType == CAMERA3_STREAM_BIDIRECTIONAL; +} + +bool Stream::isRegistered() +{ + return mRegistered; +} + +bool Stream::isValidReuseStream(int id, camera3_stream_t *s) +{ + if (id != mId) { + ALOGE("%s:%d: Invalid camera id for reuse. Got %d expect %d", + __func__, mId, id, mId); + return false; + } + if (s != mStream) { + ALOGE("%s:%d: Invalid stream handle for reuse. Got %p expect %p", + __func__, mId, s, mStream); + return false; + } + if (s->stream_type != mType) { + // TODO: prettyprint type string + ALOGE("%s:%d: Mismatched type in reused stream. Got %d expect %d", + __func__, mId, s->stream_type, mType); + return false; + } + if (s->format != mFormat) { + // TODO: prettyprint format string + ALOGE("%s:%d: Mismatched format in reused stream. Got %d expect %d", + __func__, mId, s->format, mFormat); + return false; + } + if (s->width != mWidth) { + ALOGE("%s:%d: Mismatched width in reused stream. Got %d expect %d", + __func__, mId, s->width, mWidth); + return false; + } + if (s->height != mHeight) { + ALOGE("%s:%d: Mismatched height in reused stream. Got %d expect %d", + __func__, mId, s->height, mHeight); + return false; + } + return true; +} + +int Stream::registerBuffers(const camera3_stream_buffer_set_t *buf_set) +{ + CAMTRACE_CALL(); + + if (buf_set->stream != mStream) { + ALOGE("%s:%d: Buffer set for invalid stream. Got %p expect %p", + __func__, mId, buf_set->stream, mStream); + return -EINVAL; + } + + pthread_mutex_lock(&mMutex); + + mNumBuffers = buf_set->num_buffers; + mBuffers = new buffer_handle_t*[mNumBuffers]; + + for (unsigned int i = 0; i < mNumBuffers; i++) { + ALOGV("%s:%d: Registering buffer %p", __func__, mId, + buf_set->buffers[i]); + mBuffers[i] = buf_set->buffers[i]; + // TODO: register buffers with hw, handle error cases + } + mRegistered = true; + + pthread_mutex_unlock(&mMutex); + + return 0; +} + +// This must only be called with mMutex held +void Stream::unregisterBuffers_L() +{ + mRegistered = false; + mNumBuffers = 0; + delete [] mBuffers; + // TODO: unregister buffers from hw +} + +} // namespace default_camera_hal diff --git a/modules/camera/Stream.h b/modules/camera/Stream.h new file mode 100644 index 0000000..34abd95 --- /dev/null +++ b/modules/camera/Stream.h @@ -0,0 +1,79 @@ +/* + * 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 STREAM_H_ +#define STREAM_H_ + +#include <hardware/camera3.h> +#include <hardware/gralloc.h> +#include <system/graphics.h> + +namespace default_camera_hal { +// Stream represents a single input or output stream for a camera device. +class Stream { + public: + Stream(int id, camera3_stream_t *s); + ~Stream(); + + // validate that astream's parameters match this stream's parameters + bool isValidReuseStream(int id, camera3_stream_t *s); + + // Register buffers with hardware + int registerBuffers(const camera3_stream_buffer_set_t *buf_set); + + void setUsage(uint32_t usage); + void setMaxBuffers(uint32_t max_buffers); + + int getType(); + bool isInputType(); + bool isOutputType(); + bool isRegistered(); + + // This stream is being reused. Used in stream configuration passes + bool mReuse; + + private: + // Clean up buffer state. must be called with mMutex held. + void unregisterBuffers_L(); + + // The camera device id this stream belongs to + const int mId; + // Handle to framework's stream, used as a cookie for buffers + camera3_stream_t *mStream; + // Stream type: CAMERA3_STREAM_* (see <hardware/camera3.h>) + const int mType; + // Width in pixels of the buffers in this stream + const uint32_t mWidth; + // Height in pixels of the buffers in this stream + const uint32_t mHeight; + // Gralloc format: HAL_PIXEL_FORMAT_* (see <system/graphics.h>) + const int mFormat; + // Gralloc usage mask : GRALLOC_USAGE_* (see <hardware/gralloc.h>) + uint32_t mUsage; + // Max simultaneous in-flight buffers for this stream + uint32_t mMaxBuffers; + // Buffers have been registered for this stream and are ready + bool mRegistered; + // Array of handles to buffers currently in use by the stream + buffer_handle_t **mBuffers; + // Number of buffers in mBuffers + unsigned int mNumBuffers; + // Lock protecting the Stream object for modifications + pthread_mutex_t mMutex; +}; +} // namespace default_camera_hal + +#endif // STREAM_H_ diff --git a/modules/consumerir/Android.mk b/modules/consumerir/Android.mk new file mode 100644 index 0000000..ed6aa0f --- /dev/null +++ b/modules/consumerir/Android.mk @@ -0,0 +1,25 @@ +# 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. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := consumerir.default +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw +LOCAL_SRC_FILES := consumerir.c +LOCAL_SHARED_LIBRARIES := liblog libcutils +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/modules/consumerir/consumerir.c b/modules/consumerir/consumerir.c new file mode 100644 index 0000000..83eba75 --- /dev/null +++ b/modules/consumerir/consumerir.c @@ -0,0 +1,116 @@ +/* + * 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. + */ +#define LOG_TAG "ConsumerIrHal" + +#include <errno.h> +#include <string.h> +#include <cutils/log.h> +#include <hardware/hardware.h> +#include <hardware/consumerir.h> + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) + +static const consumerir_freq_range_t consumerir_freqs[] = { + {.min = 30000, .max = 30000}, + {.min = 33000, .max = 33000}, + {.min = 36000, .max = 36000}, + {.min = 38000, .max = 38000}, + {.min = 40000, .max = 40000}, + {.min = 56000, .max = 56000}, +}; + +static int consumerir_transmit(struct consumerir_device *dev, + int carrier_freq, int pattern[], int pattern_len) +{ + int total_time = 0; + long i; + + for (i = 0; i < pattern_len; i++) + total_time += pattern[i]; + + /* simulate the time spent transmitting by sleeping */ + ALOGD("transmit for %d uS at %d Hz", total_time, carrier_freq); + usleep(total_time); + + return 0; +} + +static int consumerir_get_num_carrier_freqs(struct consumerir_device *dev) +{ + return ARRAY_SIZE(consumerir_freqs); +} + +static int consumerir_get_carrier_freqs(struct consumerir_device *dev, + size_t len, consumerir_freq_range_t *ranges) +{ + size_t to_copy = ARRAY_SIZE(consumerir_freqs); + + to_copy = len < to_copy ? len : to_copy; + memcpy(ranges, consumerir_freqs, to_copy * sizeof(consumerir_freq_range_t)); + return to_copy; +} + +static int consumerir_close(hw_device_t *dev) +{ + free(dev); + return 0; +} + +/* + * Generic device handling + */ +static int consumerir_open(const hw_module_t* module, const char* name, + hw_device_t** device) +{ + if (strcmp(name, CONSUMERIR_TRANSMITTER) != 0) { + return -EINVAL; + } + if (device == NULL) { + ALOGE("NULL device on open"); + return -EINVAL; + } + + consumerir_device_t *dev = malloc(sizeof(consumerir_device_t)); + memset(dev, 0, sizeof(consumerir_device_t)); + + dev->common.tag = HARDWARE_DEVICE_TAG; + dev->common.version = 0; + dev->common.module = (struct hw_module_t*) module; + dev->common.close = consumerir_close; + + dev->transmit = consumerir_transmit; + dev->get_num_carrier_freqs = consumerir_get_num_carrier_freqs; + dev->get_carrier_freqs = consumerir_get_carrier_freqs; + + *device = (hw_device_t*) dev; + return 0; +} + +static struct hw_module_methods_t consumerir_module_methods = { + .open = consumerir_open, +}; + +consumerir_module_t HAL_MODULE_INFO_SYM = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .module_api_version = CONSUMERIR_MODULE_API_VERSION_1_0, + .hal_api_version = HARDWARE_HAL_API_VERSION, + .id = CONSUMERIR_HARDWARE_MODULE_ID, + .name = "Demo IR HAL", + .author = "The Android Open Source Project", + .methods = &consumerir_module_methods, + }, +}; diff --git a/modules/gralloc/gralloc.cpp b/modules/gralloc/gralloc.cpp index 03d46d5..f832f35 100644 --- a/modules/gralloc/gralloc.cpp +++ b/modules/gralloc/gralloc.cpp @@ -217,8 +217,6 @@ static int gralloc_alloc(alloc_device_t* dev, bpp = 3; break; case HAL_PIXEL_FORMAT_RGB_565: - case HAL_PIXEL_FORMAT_RGBA_5551: - case HAL_PIXEL_FORMAT_RGBA_4444: case HAL_PIXEL_FORMAT_RAW_SENSOR: bpp = 2; break; |