diff options
| author | Eino-Ville Talvala <etalvala@google.com> | 2013-03-11 18:57:57 -0700 |
|---|---|---|
| committer | Eino-Ville Talvala <etalvala@google.com> | 2013-04-04 16:01:26 -0700 |
| commit | 2de81ad1fbadb0b2dd26830f6bb97c19c783969f (patch) | |
| tree | 3a81011b06cd9be93e215470a98b345c206549c0 | |
| parent | 4dc85efabf08b5b700a6ec0c9b435b40334e72c4 (diff) | |
| download | android_device_generic_goldfish-2de81ad1fbadb0b2dd26830f6bb97c19c783969f.tar.gz android_device_generic_goldfish-2de81ad1fbadb0b2dd26830f6bb97c19c783969f.tar.bz2 android_device_generic_goldfish-2de81ad1fbadb0b2dd26830f6bb97c19c783969f.zip | |
Bare-bones emulated fake camera for HAL version 3
- Uses same backend as HAL version 2 fake camera.
- No fake 3A yet
- No reprocessing support
- No JPEG support
Change-Id: I9b55b05fbeac9d42340eb988021e65491d13a2f9
| -rwxr-xr-x | camera/Android.mk | 43 | ||||
| -rw-r--r-- | camera/EmulatedCamera3.cpp | 298 | ||||
| -rw-r--r-- | camera/EmulatedCamera3.h | 204 | ||||
| -rwxr-xr-x | camera/EmulatedCameraFactory.cpp | 11 | ||||
| -rw-r--r-- | camera/EmulatedFakeCamera2.cpp | 2 | ||||
| -rw-r--r-- | camera/EmulatedFakeCamera3.cpp | 1339 | ||||
| -rw-r--r-- | camera/EmulatedFakeCamera3.h | 211 | ||||
| -rw-r--r-- | camera/fake-pipeline2/Sensor.cpp | 3 | ||||
| -rw-r--r-- | camera/fake-pipeline2/Sensor.h | 4 |
9 files changed, 2088 insertions, 27 deletions
diff --git a/camera/Android.mk b/camera/Android.mk index 0f1685c..8f20cdb 100755 --- a/camera/Android.mk +++ b/camera/Android.mk @@ -39,27 +39,28 @@ LOCAL_C_INCLUDES += external/jpeg \ LOCAL_SRC_FILES := \ EmulatedCameraHal.cpp \ - EmulatedCameraFactory.cpp \ - EmulatedBaseCamera.cpp \ - EmulatedCamera.cpp \ - EmulatedCameraDevice.cpp \ - EmulatedQemuCamera.cpp \ - EmulatedQemuCameraDevice.cpp \ - EmulatedFakeCamera.cpp \ - EmulatedFakeCameraDevice.cpp \ - Converters.cpp \ - PreviewWindow.cpp \ - CallbackNotifier.cpp \ - QemuClient.cpp \ - JpegCompressor.cpp \ - EmulatedCamera2.cpp \ - EmulatedCameraHotplugThread.cpp \ - EmulatedFakeCamera2.cpp \ - EmulatedQemuCamera2.cpp \ - fake-pipeline2/Scene.cpp \ - fake-pipeline2/Sensor.cpp \ - fake-pipeline2/JpegCompressor.cpp - + EmulatedCameraFactory.cpp \ + EmulatedCameraHotplugThread.cpp \ + EmulatedBaseCamera.cpp \ + EmulatedCamera.cpp \ + EmulatedCameraDevice.cpp \ + EmulatedQemuCamera.cpp \ + EmulatedQemuCameraDevice.cpp \ + EmulatedFakeCamera.cpp \ + EmulatedFakeCameraDevice.cpp \ + Converters.cpp \ + PreviewWindow.cpp \ + CallbackNotifier.cpp \ + QemuClient.cpp \ + JpegCompressor.cpp \ + EmulatedCamera2.cpp \ + EmulatedFakeCamera2.cpp \ + EmulatedQemuCamera2.cpp \ + fake-pipeline2/Scene.cpp \ + fake-pipeline2/Sensor.cpp \ + fake-pipeline2/JpegCompressor.cpp \ + EmulatedCamera3.cpp \ + EmulatedFakeCamera3.cpp ifeq ($(TARGET_PRODUCT),vbox_x86) LOCAL_MODULE := camera.vbox_x86 diff --git a/camera/EmulatedCamera3.cpp b/camera/EmulatedCamera3.cpp new file mode 100644 index 0000000..47de44f --- /dev/null +++ b/camera/EmulatedCamera3.cpp @@ -0,0 +1,298 @@ +/* + * 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. + */ + +/** + * Contains implementation of a class EmulatedCamera that encapsulates + * functionality common to all version 3.0 emulated camera devices. Instances + * of this class (for each emulated camera) are created during the construction + * of the EmulatedCameraFactory instance. This class serves as an entry point + * for all camera API calls that defined by camera3_device_ops_t API. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "EmulatedCamera3_Camera" +#include <cutils/log.h> + +#include "EmulatedCamera3.h" +#include "system/camera_metadata.h" + +namespace android { + +/** + * Constructs EmulatedCamera3 instance. + * Param: + * cameraId - Zero based camera identifier, which is an index of the camera + * instance in camera factory's array. + * module - Emulated camera HAL module descriptor. + */ +EmulatedCamera3::EmulatedCamera3(int cameraId, + struct hw_module_t* module): + EmulatedBaseCamera(cameraId, + CAMERA_DEVICE_API_VERSION_3_0, + &common, + module), + mStatus(STATUS_ERROR) +{ + common.close = EmulatedCamera3::close; + ops = &sDeviceOps; + + mCallbackOps = NULL; + + mVendorTagOps.get_camera_vendor_section_name = + EmulatedCamera3::get_camera_vendor_section_name; + mVendorTagOps.get_camera_vendor_tag_name = + EmulatedCamera3::get_camera_vendor_tag_name; + mVendorTagOps.get_camera_vendor_tag_type = + EmulatedCamera3::get_camera_vendor_tag_type; + mVendorTagOps.parent = this; +} + +/* Destructs EmulatedCamera3 instance. */ +EmulatedCamera3::~EmulatedCamera3() { +} + +/**************************************************************************** + * Abstract API + ***************************************************************************/ + +/**************************************************************************** + * Public API + ***************************************************************************/ + +status_t EmulatedCamera3::Initialize() { + ALOGV("%s", __FUNCTION__); + + mStatus = STATUS_CLOSED; + return NO_ERROR; +} + +/**************************************************************************** + * Camera API implementation + ***************************************************************************/ + +status_t EmulatedCamera3::connectCamera(hw_device_t** device) { + ALOGV("%s", __FUNCTION__); + if (device == NULL) return BAD_VALUE; + + if (mStatus != STATUS_CLOSED) { + ALOGE("%s: Trying to open a camera in state %d!", + __FUNCTION__, mStatus); + return INVALID_OPERATION; + } + + *device = &common; + mStatus = STATUS_OPEN; + return NO_ERROR; +} + +status_t EmulatedCamera3::closeCamera() { + mStatus = STATUS_CLOSED; + return NO_ERROR; +} + +status_t EmulatedCamera3::getCameraInfo(struct camera_info* info) { + return EmulatedBaseCamera::getCameraInfo(info); +} + +/**************************************************************************** + * Camera Device API implementation. + * These methods are called from the camera API callback routines. + ***************************************************************************/ + +status_t EmulatedCamera3::initializeDevice( + const camera3_callback_ops *callbackOps) { + if (callbackOps == NULL) { + ALOGE("%s: NULL callback ops provided to HAL!", + __FUNCTION__); + return BAD_VALUE; + } + + if (mStatus != STATUS_OPEN) { + ALOGE("%s: Trying to initialize a camera in state %d!", + __FUNCTION__, mStatus); + return INVALID_OPERATION; + } + + mCallbackOps = callbackOps; + mStatus = STATUS_READY; + + return NO_ERROR; +} + +status_t EmulatedCamera3::configureStreams( + camera3_stream_configuration *streamList) { + ALOGE("%s: Not implemented", __FUNCTION__); + return INVALID_OPERATION; +} + +status_t EmulatedCamera3::registerStreamBuffers( + const camera3_stream_buffer_set *bufferSet) { + ALOGE("%s: Not implemented", __FUNCTION__); + return INVALID_OPERATION; +} + +const camera_metadata_t* EmulatedCamera3::constructDefaultRequestSettings( + int type) { + ALOGE("%s: Not implemented", __FUNCTION__); + return NULL; +} + +status_t EmulatedCamera3::processCaptureRequest( + camera3_capture_request *request) { + ALOGE("%s: Not implemented", __FUNCTION__); + return INVALID_OPERATION; +} + +/** Custom tag query methods */ + +const char* EmulatedCamera3::getVendorSectionName(uint32_t tag) { + ALOGE("%s: Not implemented", __FUNCTION__); + return NULL; +} + +const char* EmulatedCamera3::getVendorTagName(uint32_t tag) { + ALOGE("%s: Not implemented", __FUNCTION__); + return NULL; +} + +int EmulatedCamera3::getVendorTagType(uint32_t tag) { + ALOGE("%s: Not implemented", __FUNCTION__); + return -1; +} + +/** Debug methods */ + +void EmulatedCamera3::dump(int fd) { + ALOGE("%s: Not implemented", __FUNCTION__); + return; +} + +/**************************************************************************** + * Protected API. Callbacks to the framework. + ***************************************************************************/ + +void EmulatedCamera3::sendCaptureResult(camera3_capture_result_t *result) { + mCallbackOps->process_capture_result(mCallbackOps, result); +} + +void EmulatedCamera3::sendNotify(camera3_notify_msg_t *msg) { + mCallbackOps->notify(mCallbackOps, msg); +} + +/**************************************************************************** + * Private API. + ***************************************************************************/ + +/**************************************************************************** + * Camera API callbacks as defined by camera3_device_ops structure. See + * hardware/libhardware/include/hardware/camera3.h for information on each + * of these callbacks. Implemented in this class, these callbacks simply + * dispatch the call into an instance of EmulatedCamera3 class defined by the + * 'camera_device3' parameter, or set a member value in the same. + ***************************************************************************/ + +EmulatedCamera3* getInstance(const camera3_device_t *d) { + const EmulatedCamera3* cec = static_cast<const EmulatedCamera3*>(d); + return const_cast<EmulatedCamera3*>(cec); +} + +int EmulatedCamera3::initialize(const struct camera3_device *d, + const camera3_callback_ops_t *callback_ops) { + EmulatedCamera3* ec = getInstance(d); + return ec->initializeDevice(callback_ops); +} + +int EmulatedCamera3::configure_streams(const struct camera3_device *d, + camera3_stream_configuration_t *stream_list) { + EmulatedCamera3* ec = getInstance(d); + return ec->configureStreams(stream_list); +} + +int EmulatedCamera3::register_stream_buffers( + const struct camera3_device *d, + const camera3_stream_buffer_set_t *buffer_set) { + EmulatedCamera3* ec = getInstance(d); + return ec->registerStreamBuffers(buffer_set); +} + +int EmulatedCamera3::process_capture_request( + const struct camera3_device *d, + camera3_capture_request_t *request) { + EmulatedCamera3* ec = getInstance(d); + return ec->processCaptureRequest(request); +} + +const camera_metadata_t* EmulatedCamera3::construct_default_request_settings( + const camera3_device_t *d, int type) { + EmulatedCamera3* ec = getInstance(d); + return ec->constructDefaultRequestSettings(type); +} + +void EmulatedCamera3::get_metadata_vendor_tag_ops(const camera3_device_t *d, + vendor_tag_query_ops_t *ops) { + ops->get_camera_vendor_section_name = get_camera_vendor_section_name; + ops->get_camera_vendor_tag_name = get_camera_vendor_tag_name; + ops->get_camera_vendor_tag_type = get_camera_vendor_tag_type; +} + +const char* EmulatedCamera3::get_camera_vendor_section_name( + const vendor_tag_query_ops_t *v, + uint32_t tag) { + EmulatedCamera3* ec = static_cast<const TagOps*>(v)->parent; + return ec->getVendorSectionName(tag); +} + +const char* EmulatedCamera3::get_camera_vendor_tag_name( + const vendor_tag_query_ops_t *v, + uint32_t tag) { + EmulatedCamera3* ec = static_cast<const TagOps*>(v)->parent; + return ec->getVendorTagName(tag); +} + +int EmulatedCamera3::get_camera_vendor_tag_type( + const vendor_tag_query_ops_t *v, + uint32_t tag) { + EmulatedCamera3* ec = static_cast<const TagOps*>(v)->parent; + return ec->getVendorTagType(tag); +} + +void EmulatedCamera3::dump(const camera3_device_t *d, int fd) { + EmulatedCamera3* ec = getInstance(d); + ec->dump(fd); +} + +int EmulatedCamera3::close(struct hw_device_t* device) { + EmulatedCamera3* ec = + static_cast<EmulatedCamera3*>( + reinterpret_cast<camera3_device_t*>(device) ); + if (ec == NULL) { + ALOGE("%s: Unexpected NULL camera3 device", __FUNCTION__); + return BAD_VALUE; + } + return ec->closeCamera(); +} + +camera3_device_ops_t EmulatedCamera3::sDeviceOps = { + EmulatedCamera3::initialize, + EmulatedCamera3::configure_streams, + EmulatedCamera3::register_stream_buffers, + EmulatedCamera3::construct_default_request_settings, + EmulatedCamera3::process_capture_request, + EmulatedCamera3::get_metadata_vendor_tag_ops, + EmulatedCamera3::dump +}; + +}; /* namespace android */ diff --git a/camera/EmulatedCamera3.h b/camera/EmulatedCamera3.h new file mode 100644 index 0000000..c1bddf6 --- /dev/null +++ b/camera/EmulatedCamera3.h @@ -0,0 +1,204 @@ +/* + * 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 HW_EMULATOR_CAMERA_EMULATED_CAMERA3_H +#define HW_EMULATOR_CAMERA_EMULATED_CAMERA3_H + +/** + * Contains declaration of a class EmulatedCamera that encapsulates + * functionality common to all version 3.0 emulated camera devices. Instances + * of this class (for each emulated camera) are created during the construction + * of the EmulatedCameraFactory instance. This class serves as an entry point + * for all camera API calls that defined by camera3_device_ops_t API. + */ + +#include "hardware/camera3.h" +#include "system/camera_metadata.h" +#include "EmulatedBaseCamera.h" + +namespace android { + +/** + * Encapsulates functionality common to all version 3.0 emulated camera devices + * + * Note that EmulatedCameraFactory instantiates an object of this class just + * once, when EmulatedCameraFactory instance gets constructed. Connection to / + * disconnection from the actual camera device is handled by calls to + * connectDevice(), and closeCamera() methods of this class that are invoked in + * response to hw_module_methods_t::open, and camera_device::close callbacks. + */ +class EmulatedCamera3 : public camera3_device, public EmulatedBaseCamera { +public: + /* Constructs EmulatedCamera3 instance. + * Param: + * cameraId - Zero based camera identifier, which is an index of the camera + * instance in camera factory's array. + * module - Emulated camera HAL module descriptor. + */ + EmulatedCamera3(int cameraId, + struct hw_module_t* module); + + /* Destructs EmulatedCamera2 instance. */ + virtual ~EmulatedCamera3(); + + /**************************************************************************** + * Abstract API + ***************************************************************************/ + +public: + + /**************************************************************************** + * Public API + ***************************************************************************/ + +public: + virtual status_t Initialize(); + + /**************************************************************************** + * Camera module API and generic hardware device API implementation + ***************************************************************************/ + +public: + virtual status_t connectCamera(hw_device_t** device); + + virtual status_t closeCamera(); + + virtual status_t getCameraInfo(struct camera_info* info); + + /**************************************************************************** + * Camera API implementation. + * These methods are called from the camera API callback routines. + ***************************************************************************/ + +protected: + + virtual status_t initializeDevice( + const camera3_callback_ops *callbackOps); + + virtual status_t configureStreams( + camera3_stream_configuration *streamList); + + virtual status_t registerStreamBuffers( + const camera3_stream_buffer_set *bufferSet) ; + + virtual const camera_metadata_t* constructDefaultRequestSettings( + int type); + + virtual status_t processCaptureRequest(camera3_capture_request *request); + + /** Debug methods */ + + virtual void dump(int fd); + + /** Tag query methods */ + virtual const char *getVendorSectionName(uint32_t tag); + + virtual const char *getVendorTagName(uint32_t tag); + + virtual int getVendorTagType(uint32_t tag); + + /**************************************************************************** + * Camera API callbacks as defined by camera3_device_ops structure. See + * hardware/libhardware/include/hardware/camera3.h for information on each + * of these callbacks. Implemented in this class, these callbacks simply + * dispatch the call into an instance of EmulatedCamera3 class defined in + * the 'camera_device3' parameter. + ***************************************************************************/ + +private: + + /** Startup */ + static int initialize(const struct camera3_device *, + const camera3_callback_ops_t *callback_ops); + + /** Stream configuration and buffer registration */ + + static int configure_streams(const struct camera3_device *, + camera3_stream_configuration_t *stream_list); + + static int register_stream_buffers(const struct camera3_device *, + const camera3_stream_buffer_set_t *buffer_set); + + /** Template request settings provision */ + + static const camera_metadata_t* construct_default_request_settings( + const struct camera3_device *, int type); + + /** Submission of capture requests to HAL */ + + static int process_capture_request(const struct camera3_device *, + camera3_capture_request_t *request); + + /** Vendor metadata registration */ + static void get_metadata_vendor_tag_ops(const camera3_device_t *, + vendor_tag_query_ops_t *ops); + // for get_metadata_vendor_tag_ops + static const char* get_camera_vendor_section_name( + const vendor_tag_query_ops_t *, + uint32_t tag); + static const char* get_camera_vendor_tag_name( + const vendor_tag_query_ops_t *, + uint32_t tag); + static int get_camera_vendor_tag_type( + const vendor_tag_query_ops_t *, + uint32_t tag); + + static void dump(const camera3_device_t *, int fd); + + /** For hw_device_t ops */ + static int close(struct hw_device_t* device); + + /**************************************************************************** + * Data members shared with implementations + ***************************************************************************/ + protected: + + struct TagOps : public vendor_tag_query_ops { + EmulatedCamera3 *parent; + }; + TagOps mVendorTagOps; + + enum { + // State at construction time, and after a device operation error + STATUS_ERROR = 0, + // State after startup-time init and after device instance close + STATUS_CLOSED, + // State after being opened, before device instance init + STATUS_OPEN, + // State after device instance initialization + STATUS_READY, + // State while actively capturing data + STATUS_ACTIVE + } mStatus; + + /** + * Callbacks back to the framework + */ + + void sendCaptureResult(camera3_capture_result_t *result); + void sendNotify(camera3_notify_msg_t *msg); + + /**************************************************************************** + * Data members + ***************************************************************************/ + private: + static camera3_device_ops_t sDeviceOps; + const camera3_callback_ops_t *mCallbackOps; +}; + +}; /* namespace android */ + +#endif /* HW_EMULATOR_CAMERA_EMULATED_CAMERA3_H */ diff --git a/camera/EmulatedCameraFactory.cpp b/camera/EmulatedCameraFactory.cpp index d36a215..0a8ada7 100755 --- a/camera/EmulatedCameraFactory.cpp +++ b/camera/EmulatedCameraFactory.cpp @@ -26,6 +26,7 @@ #include "EmulatedQemuCamera.h" #include "EmulatedFakeCamera.h" #include "EmulatedFakeCamera2.h" +#include "EmulatedFakeCamera3.h" #include "EmulatedCameraHotplugThread.h" #include "EmulatedCameraFactory.h" @@ -86,6 +87,11 @@ EmulatedCameraFactory::EmulatedCameraFactory() new EmulatedFakeCamera2(camera_id, true, &HAL_MODULE_INFO_SYM.common); break; + case 3: + mEmulatedCameras[camera_id] = + new EmulatedFakeCamera3(camera_id, true, + &HAL_MODULE_INFO_SYM.common); + break; default: ALOGE("%s: Unknown back camera hal version requested: %d", __FUNCTION__, getBackCameraHalVersion()); @@ -137,6 +143,11 @@ EmulatedCameraFactory::EmulatedCameraFactory() new EmulatedFakeCamera2(camera_id, false, &HAL_MODULE_INFO_SYM.common); break; + case 3: + mEmulatedCameras[camera_id] = + new EmulatedFakeCamera3(camera_id, false, + &HAL_MODULE_INFO_SYM.common); + break; default: ALOGE("%s: Unknown front camera hal version requested: %d", __FUNCTION__, diff --git a/camera/EmulatedFakeCamera2.cpp b/camera/EmulatedFakeCamera2.cpp index ab69063..0fe3a30 100644 --- a/camera/EmulatedFakeCamera2.cpp +++ b/camera/EmulatedFakeCamera2.cpp @@ -157,7 +157,7 @@ status_t EmulatedFakeCamera2::connectCamera(hw_device_t** device) { mConfigureThread = new ConfigureThread(this); mReadoutThread = new ReadoutThread(this); mControlThread = new ControlThread(this); - mSensor = new Sensor(this); + mSensor = new Sensor(); mJpegCompressor = new JpegCompressor(this); mNextStreamId = 1; diff --git a/camera/EmulatedFakeCamera3.cpp b/camera/EmulatedFakeCamera3.cpp new file mode 100644 index 0000000..8fd4df0 --- /dev/null +++ b/camera/EmulatedFakeCamera3.cpp @@ -0,0 +1,1339 @@ +/* + * 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. + */ + +/* + * Contains implementation of a class EmulatedFakeCamera3 that encapsulates + * functionality of an advanced fake camera. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "EmulatedCamera_FakeCamera3" +#include <utils/Log.h> + +#include "EmulatedFakeCamera3.h" +#include "EmulatedCameraFactory.h" +#include <ui/Fence.h> +#include <ui/Rect.h> +#include <ui/GraphicBufferMapper.h> +#include "gralloc_cb.h" +#include "fake-pipeline2/Sensor.h" +#include "fake-pipeline2/JpegCompressor.h" + +namespace android { + +/** + * Constants for camera capabilities + */ + +const int64_t USEC = 1000LL; +const int64_t MSEC = USEC * 1000LL; +const int64_t SEC = MSEC * 1000LL; + +const uint32_t EmulatedFakeCamera3::kAvailableFormats[4] = { + HAL_PIXEL_FORMAT_RAW_SENSOR, + HAL_PIXEL_FORMAT_BLOB, + HAL_PIXEL_FORMAT_RGBA_8888, + // HAL_PIXEL_FORMAT_YV12, + HAL_PIXEL_FORMAT_YCrCb_420_SP +}; + +const uint32_t EmulatedFakeCamera3::kAvailableRawSizes[2] = { + 640, 480 + // Sensor::kResolution[0], Sensor::kResolution[1] +}; + +const uint64_t EmulatedFakeCamera3::kAvailableRawMinDurations[1] = { + (const uint64_t)Sensor::kFrameDurationRange[0] +}; + +const uint32_t EmulatedFakeCamera3::kAvailableProcessedSizesBack[4] = { + 640, 480, 320, 240 + // Sensor::kResolution[0], Sensor::kResolution[1] +}; + +const uint32_t EmulatedFakeCamera3::kAvailableProcessedSizesFront[4] = { + 320, 240, 160, 120 + // Sensor::kResolution[0], Sensor::kResolution[1] +}; + +const uint64_t EmulatedFakeCamera3::kAvailableProcessedMinDurations[1] = { + (const uint64_t)Sensor::kFrameDurationRange[0] +}; + +const uint32_t EmulatedFakeCamera3::kAvailableJpegSizesBack[2] = { + 640, 480 + // Sensor::kResolution[0], Sensor::kResolution[1] +}; + +const uint32_t EmulatedFakeCamera3::kAvailableJpegSizesFront[2] = { + 320, 240 + // Sensor::kResolution[0], Sensor::kResolution[1] +}; + + +const uint64_t EmulatedFakeCamera3::kAvailableJpegMinDurations[1] = { + (const uint64_t)Sensor::kFrameDurationRange[0] +}; + +/** + * Camera device lifecycle methods + */ + +EmulatedFakeCamera3::EmulatedFakeCamera3(int cameraId, bool facingBack, + struct hw_module_t* module) : + EmulatedCamera3(cameraId, module), + mFacingBack(facingBack) { + ALOGD("Constructing emulated fake camera 3 facing %s", + facingBack ? "back" : "front"); + + for (size_t i = 0; i < CAMERA3_TEMPLATE_COUNT; i++) { + mDefaultTemplates[i] = NULL; + } +} + +EmulatedFakeCamera3::~EmulatedFakeCamera3() { + for (size_t i = 0; i < CAMERA3_TEMPLATE_COUNT; i++) { + if (mDefaultTemplates[i] != NULL) { + free_camera_metadata(mDefaultTemplates[i]); + } + } +} + +status_t EmulatedFakeCamera3::Initialize() { + ALOGV("%s: E", __FUNCTION__); + status_t res; + + if (mStatus != STATUS_ERROR) { + ALOGE("%s: Already initialized!", __FUNCTION__); + return INVALID_OPERATION; + } + + res = constructStaticInfo(); + if (res != OK) { + ALOGE("%s: Unable to allocate static info: %s (%d)", + __FUNCTION__, strerror(-res), res); + return res; + } + + return EmulatedCamera3::Initialize(); +} + +status_t EmulatedFakeCamera3::connectCamera(hw_device_t** device) { + ALOGV("%s: E", __FUNCTION__); + Mutex::Autolock l(mLock); + status_t res; + + if (mStatus != STATUS_CLOSED) { + ALOGE("%s: Can't connect in state %d", __FUNCTION__, mStatus); + return INVALID_OPERATION; + } + + mSensor = new Sensor(); + + res = mSensor->startUp(); + if (res != NO_ERROR) return res; + + mReadoutThread = new ReadoutThread(this); + + res = mReadoutThread->run("EmuCam3::readoutThread"); + if (res != NO_ERROR) return res; + + return EmulatedCamera3::connectCamera(device); +} + +status_t EmulatedFakeCamera3::closeCamera() { + ALOGV("%s: E", __FUNCTION__); + status_t res; + { + Mutex::Autolock l(mLock); + if (mStatus == STATUS_CLOSED) return OK; + + res = mSensor->shutDown(); + if (res != NO_ERROR) { + ALOGE("%s: Unable to shut down sensor: %d", __FUNCTION__, res); + return res; + } + mSensor.clear(); + + mReadoutThread->requestExit(); + } + + mReadoutThread->join(); + + { + Mutex::Autolock l(mLock); + // Clear out private stream information + for (StreamIterator s = mStreams.begin(); s != mStreams.end(); s++) { + PrivateStreamInfo *privStream = + static_cast<PrivateStreamInfo*>((*s)->priv); + delete privStream; + (*s)->priv = NULL; + } + mStreams.clear(); + mReadoutThread.clear(); + } + + return EmulatedCamera3::closeCamera(); +} + +status_t EmulatedFakeCamera3::getCameraInfo(struct camera_info *info) { + info->facing = mFacingBack ? CAMERA_FACING_BACK : CAMERA_FACING_FRONT; + info->orientation = gEmulatedCameraFactory.getFakeCameraOrientation(); + return EmulatedCamera3::getCameraInfo(info); +} + +/** + * Camera3 interface methods + */ + +status_t EmulatedFakeCamera3::configureStreams( + camera3_stream_configuration *streamList) { + Mutex::Autolock l(mLock); + ALOGV("%s: %d streams", __FUNCTION__, streamList->num_streams); + + if (mStatus != STATUS_OPEN && mStatus != STATUS_READY) { + ALOGE("%s: Cannot configure streams in state %d", + __FUNCTION__, mStatus); + return NO_INIT; + } + + /** + * Sanity-check input list. + */ + if (streamList == NULL) { + ALOGE("%s: NULL stream configuration", __FUNCTION__); + return BAD_VALUE; + } + + if (streamList->streams == NULL) { + ALOGE("%s: NULL stream list", __FUNCTION__); + return BAD_VALUE; + } + + if (streamList->num_streams < 1) { + ALOGE("%s: Bad number of streams requested: %d", __FUNCTION__, + streamList->num_streams); + return BAD_VALUE; + } + + camera3_stream_t *inputStream = NULL; + for (size_t i = 0; i < streamList->num_streams; i++) { + camera3_stream_t *newStream = streamList->streams[i]; + if (newStream->stream_type == CAMERA3_STREAM_INPUT) { + if (inputStream != NULL) { + + ALOGE("%s: Multiple input streams requested!", __FUNCTION__); + return BAD_VALUE; + } + inputStream = newStream; + } + } + mInputStream = inputStream; + + /** + * Initially mark all existing streams as not alive + */ + for (StreamIterator s = mStreams.begin(); s != mStreams.end(); ++s) { + PrivateStreamInfo *privStream = + static_cast<PrivateStreamInfo*>((*s)->priv); + privStream->alive = false; + } + + /** + * Find new streams and mark still-alive ones + */ + for (size_t i = 0; i < streamList->num_streams; i++) { + camera3_stream_t *newStream = streamList->streams[i]; + if (newStream->priv == NULL) { + // New stream, construct info + PrivateStreamInfo *privStream = new PrivateStreamInfo(); + privStream->alive = true; + privStream->registered = false; + + switch (newStream->stream_type) { + case CAMERA3_STREAM_OUTPUT: + newStream->usage = GRALLOC_USAGE_HW_CAMERA_WRITE; + break; + case CAMERA3_STREAM_INPUT: + newStream->usage = GRALLOC_USAGE_HW_CAMERA_READ; + break; + case CAMERA3_STREAM_BIDIRECTIONAL: + newStream->usage = GRALLOC_USAGE_HW_CAMERA_READ | + GRALLOC_USAGE_HW_CAMERA_WRITE; + break; + } + newStream->max_buffers = kMaxBufferCount; + newStream->priv = privStream; + mStreams.push_back(newStream); + } else { + // Existing stream, mark as still alive. + PrivateStreamInfo *privStream = + static_cast<PrivateStreamInfo*>(newStream->priv); + privStream->alive = true; + } + } + + /** + * Reap the dead streams + */ + for (StreamIterator s = mStreams.begin(); s != mStreams.end();) { + PrivateStreamInfo *privStream = + static_cast<PrivateStreamInfo*>((*s)->priv); + if (!privStream->alive) { + (*s)->priv = NULL; + delete privStream; + s = mStreams.erase(s); + } else { + ++s; + } + } + + /** + * Can't reuse settings across configure call + */ + mPrevSettings.clear(); + + return OK; +} + +status_t EmulatedFakeCamera3::registerStreamBuffers( + const camera3_stream_buffer_set *bufferSet) { + ALOGV("%s: E", __FUNCTION__); + Mutex::Autolock l(mLock); + + /** + * Sanity checks + */ + + if (mStatus != STATUS_READY) { + ALOGE("%s: Cannot register buffers in state %d", + __FUNCTION__, mStatus); + return NO_INIT; + } + + if (bufferSet == NULL) { + ALOGE("%s: NULL buffer set!", __FUNCTION__); + return BAD_VALUE; + } + + StreamIterator s = mStreams.begin(); + for (; s != mStreams.end(); ++s) { + if (bufferSet->stream == *s) break; + } + if (s == mStreams.end()) { + ALOGE("%s: Trying to register buffers for a non-configured stream!", + __FUNCTION__); + return BAD_VALUE; + } + + /** + * Register the buffers. This doesn't mean anything to the emulator besides + * marking them off as registered. + */ + + PrivateStreamInfo *privStream = + static_cast<PrivateStreamInfo*>((*s)->priv); + privStream->registered = true; + + return OK; +} + +const camera_metadata_t* EmulatedFakeCamera3::constructDefaultRequestSettings( + int type) { + ALOGV("%s: E", __FUNCTION__); + Mutex::Autolock l(mLock); + + if (type < 0 || type >= CAMERA2_TEMPLATE_COUNT) { + ALOGE("%s: Unknown request settings template: %d", + __FUNCTION__, type); + return NULL; + } + + /** + * Cache is not just an optimization - pointer returned has to live at + * least as long as the camera device instance does. + */ + if (mDefaultTemplates[type] != NULL) { + return mDefaultTemplates[type]; + } + + CameraMetadata settings; + + /** android.request */ + + static const uint8_t requestType = ANDROID_REQUEST_TYPE_CAPTURE; + settings.update(ANDROID_REQUEST_TYPE, &requestType, 1); + + static const uint8_t metadataMode = ANDROID_REQUEST_METADATA_MODE_FULL; + settings.update(ANDROID_REQUEST_METADATA_MODE, &metadataMode, 1); + + static const int32_t id = 0; + settings.update(ANDROID_REQUEST_ID, &id, 1); + + static const int32_t frameCount = 0; + settings.update(ANDROID_REQUEST_FRAME_COUNT, &frameCount, 1); + + /** android.lens */ + + static const float focusDistance = 0; + settings.update(ANDROID_LENS_FOCUS_DISTANCE, &focusDistance, 1); + + static const float aperture = 2.8f; + settings.update(ANDROID_LENS_APERTURE, &aperture, 1); + + static const float focalLength = 5.0f; + settings.update(ANDROID_LENS_FOCAL_LENGTH, &focalLength, 1); + + static const float filterDensity = 0; + settings.update(ANDROID_LENS_FILTER_DENSITY, &filterDensity, 1); + + static const uint8_t opticalStabilizationMode = + ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF; + settings.update(ANDROID_LENS_OPTICAL_STABILIZATION_MODE, + &opticalStabilizationMode, 1); + + // FOCUS_RANGE set only in frame + + /** android.sensor */ + + static const int64_t exposureTime = 10 * MSEC; + settings.update(ANDROID_SENSOR_EXPOSURE_TIME, &exposureTime, 1); + + static const int64_t frameDuration = 33333333L; // 1/30 s + settings.update(ANDROID_SENSOR_FRAME_DURATION, &frameDuration, 1); + + static const int32_t sensitivity = 100; + settings.update(ANDROID_SENSOR_SENSITIVITY, &sensitivity, 1); + + // TIMESTAMP set only in frame + + /** android.flash */ + + static const uint8_t flashMode = ANDROID_FLASH_MODE_OFF; + settings.update(ANDROID_FLASH_MODE, &flashMode, 1); + + static const uint8_t flashPower = 10; + settings.update(ANDROID_FLASH_FIRING_POWER, &flashPower, 1); + + static const int64_t firingTime = 0; + settings.update(ANDROID_FLASH_FIRING_TIME, &firingTime, 1); + + /** Processing block modes */ + uint8_t hotPixelMode = 0; + uint8_t demosaicMode = 0; + uint8_t noiseMode = 0; + uint8_t shadingMode = 0; + uint8_t geometricMode = 0; + uint8_t colorMode = 0; + uint8_t tonemapMode = 0; + uint8_t edgeMode = 0; + switch (type) { + case CAMERA2_TEMPLATE_STILL_CAPTURE: + // fall-through + case CAMERA2_TEMPLATE_VIDEO_SNAPSHOT: + // fall-through + case CAMERA2_TEMPLATE_ZERO_SHUTTER_LAG: + hotPixelMode = ANDROID_HOT_PIXEL_MODE_HIGH_QUALITY; + demosaicMode = ANDROID_DEMOSAIC_MODE_HIGH_QUALITY; + noiseMode = ANDROID_NOISE_REDUCTION_MODE_HIGH_QUALITY; + shadingMode = ANDROID_SHADING_MODE_HIGH_QUALITY; + geometricMode = ANDROID_GEOMETRIC_MODE_HIGH_QUALITY; + colorMode = ANDROID_COLOR_CORRECTION_MODE_HIGH_QUALITY; + tonemapMode = ANDROID_TONEMAP_MODE_HIGH_QUALITY; + edgeMode = ANDROID_EDGE_MODE_HIGH_QUALITY; + break; + case CAMERA2_TEMPLATE_PREVIEW: + // fall-through + case CAMERA2_TEMPLATE_VIDEO_RECORD: + // fall-through + default: + hotPixelMode = ANDROID_HOT_PIXEL_MODE_FAST; + demosaicMode = ANDROID_DEMOSAIC_MODE_FAST; + noiseMode = ANDROID_NOISE_REDUCTION_MODE_FAST; + shadingMode = ANDROID_SHADING_MODE_FAST; + geometricMode = ANDROID_GEOMETRIC_MODE_FAST; + colorMode = ANDROID_COLOR_CORRECTION_MODE_FAST; + tonemapMode = ANDROID_TONEMAP_MODE_FAST; + edgeMode = ANDROID_EDGE_MODE_FAST; + break; + } + settings.update(ANDROID_HOT_PIXEL_MODE, &hotPixelMode, 1); + settings.update(ANDROID_DEMOSAIC_MODE, &demosaicMode, 1); + settings.update(ANDROID_NOISE_REDUCTION_MODE, &noiseMode, 1); + settings.update(ANDROID_SHADING_MODE, &shadingMode, 1); + settings.update(ANDROID_GEOMETRIC_MODE, &geometricMode, 1); + settings.update(ANDROID_COLOR_CORRECTION_MODE, &colorMode, 1); + settings.update(ANDROID_TONEMAP_MODE, &tonemapMode, 1); + settings.update(ANDROID_EDGE_MODE, &edgeMode, 1); + + /** android.noise */ + static const uint8_t noiseStrength = 5; + settings.update(ANDROID_NOISE_REDUCTION_STRENGTH, &noiseStrength, 1); + + /** android.color */ + static const float colorTransform[9] = { + 1.0f, 0.f, 0.f, + 0.f, 1.f, 0.f, + 0.f, 0.f, 1.f + }; + settings.update(ANDROID_COLOR_CORRECTION_TRANSFORM, colorTransform, 9); + + /** android.tonemap */ + static const float tonemapCurve[4] = { + 0.f, 0.f, + 1.f, 1.f + }; + settings.update(ANDROID_TONEMAP_CURVE_RED, tonemapCurve, 4); + settings.update(ANDROID_TONEMAP_CURVE_GREEN, tonemapCurve, 4); + settings.update(ANDROID_TONEMAP_CURVE_BLUE, tonemapCurve, 4); + + /** android.edge */ + static const uint8_t edgeStrength = 5; + settings.update(ANDROID_EDGE_STRENGTH, &edgeStrength, 1); + + /** android.scaler */ + static const int32_t cropRegion[3] = { + 0, 0, (int32_t)Sensor::kResolution[0] + }; + settings.update(ANDROID_SCALER_CROP_REGION, cropRegion, 3); + + /** android.jpeg */ + static const uint8_t jpegQuality = 80; + settings.update(ANDROID_JPEG_QUALITY, &jpegQuality, 1); + + static const int32_t thumbnailSize[2] = { + 640, 480 + }; + settings.update(ANDROID_JPEG_THUMBNAIL_SIZE, thumbnailSize, 2); + + static const uint8_t thumbnailQuality = 80; + settings.update(ANDROID_JPEG_THUMBNAIL_QUALITY, &thumbnailQuality, 1); + + static const double gpsCoordinates[2] = { + 0, 0 + }; + settings.update(ANDROID_JPEG_GPS_COORDINATES, gpsCoordinates, 2); + + static const uint8_t gpsProcessingMethod[32] = "None"; + settings.update(ANDROID_JPEG_GPS_PROCESSING_METHOD, gpsProcessingMethod, 32); + + static const int64_t gpsTimestamp = 0; + settings.update(ANDROID_JPEG_GPS_TIMESTAMP, &gpsTimestamp, 1); + + static const int32_t jpegOrientation = 0; + settings.update(ANDROID_JPEG_ORIENTATION, &jpegOrientation, 1); + + /** android.stats */ + + static const uint8_t faceDetectMode = + ANDROID_STATISTICS_FACE_DETECT_MODE_OFF; + settings.update(ANDROID_STATISTICS_FACE_DETECT_MODE, &faceDetectMode, 1); + + static const uint8_t histogramMode = ANDROID_STATISTICS_HISTOGRAM_MODE_OFF; + settings.update(ANDROID_STATISTICS_HISTOGRAM_MODE, &histogramMode, 1); + + static const uint8_t sharpnessMapMode = + ANDROID_STATISTICS_SHARPNESS_MAP_MODE_OFF; + settings.update(ANDROID_STATISTICS_SHARPNESS_MAP_MODE, &sharpnessMapMode, 1); + + // faceRectangles, faceScores, faceLandmarks, faceIds, histogram, + // sharpnessMap only in frames + + /** android.control */ + + uint8_t controlIntent = 0; + switch (type) { + case CAMERA2_TEMPLATE_PREVIEW: + controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW; + break; + case CAMERA2_TEMPLATE_STILL_CAPTURE: + controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE; + break; + case CAMERA2_TEMPLATE_VIDEO_RECORD: + controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD; + break; + case CAMERA2_TEMPLATE_VIDEO_SNAPSHOT: + controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT; + break; + case CAMERA2_TEMPLATE_ZERO_SHUTTER_LAG: + controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG; + break; + default: + controlIntent = ANDROID_CONTROL_CAPTURE_INTENT_CUSTOM; + break; + } + settings.update(ANDROID_CONTROL_CAPTURE_INTENT, &controlIntent, 1); + + static const uint8_t controlMode = ANDROID_CONTROL_MODE_AUTO; + settings.update(ANDROID_CONTROL_MODE, &controlMode, 1); + + static const uint8_t effectMode = ANDROID_CONTROL_EFFECT_MODE_OFF; + settings.update(ANDROID_CONTROL_EFFECT_MODE, &effectMode, 1); + + static const uint8_t sceneMode = ANDROID_CONTROL_SCENE_MODE_FACE_PRIORITY; + settings.update(ANDROID_CONTROL_SCENE_MODE, &sceneMode, 1); + + static const uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH; + settings.update(ANDROID_CONTROL_AE_MODE, &aeMode, 1); + + static const uint8_t aeLock = ANDROID_CONTROL_AE_LOCK_OFF; + settings.update(ANDROID_CONTROL_AE_LOCK, &aeLock, 1); + + static const int32_t controlRegions[5] = { + 0, 0, (int32_t)Sensor::kResolution[0], (int32_t)Sensor::kResolution[1], + 1000 + }; + settings.update(ANDROID_CONTROL_AE_REGIONS, controlRegions, 5); + + static const int32_t aeExpCompensation = 0; + settings.update(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION, &aeExpCompensation, 1); + + static const int32_t aeTargetFpsRange[2] = { + 10, 30 + }; + settings.update(ANDROID_CONTROL_AE_TARGET_FPS_RANGE, aeTargetFpsRange, 2); + + static const uint8_t aeAntibandingMode = + ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO; + settings.update(ANDROID_CONTROL_AE_ANTIBANDING_MODE, &aeAntibandingMode, 1); + + static const uint8_t awbMode = + ANDROID_CONTROL_AWB_MODE_AUTO; + settings.update(ANDROID_CONTROL_AWB_MODE, &awbMode, 1); + + static const uint8_t awbLock = ANDROID_CONTROL_AWB_LOCK_OFF; + settings.update(ANDROID_CONTROL_AWB_LOCK, &awbLock, 1); + + settings.update(ANDROID_CONTROL_AWB_REGIONS, controlRegions, 5); + + uint8_t afMode = 0; + switch (type) { + case CAMERA2_TEMPLATE_PREVIEW: + afMode = ANDROID_CONTROL_AF_MODE_AUTO; + break; + case CAMERA2_TEMPLATE_STILL_CAPTURE: + afMode = ANDROID_CONTROL_AF_MODE_AUTO; + break; + case CAMERA2_TEMPLATE_VIDEO_RECORD: + afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO; + break; + case CAMERA2_TEMPLATE_VIDEO_SNAPSHOT: + afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO; + break; + case CAMERA2_TEMPLATE_ZERO_SHUTTER_LAG: + afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE; + break; + default: + afMode = ANDROID_CONTROL_AF_MODE_AUTO; + break; + } + settings.update(ANDROID_CONTROL_AF_MODE, &afMode, 1); + + settings.update(ANDROID_CONTROL_AF_REGIONS, controlRegions, 5); + + static const uint8_t vstabMode = + ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF; + settings.update(ANDROID_CONTROL_VIDEO_STABILIZATION_MODE, &vstabMode, 1); + + // aeState, awbState, afState only in frame + + mDefaultTemplates[type] = settings.release(); + + return mDefaultTemplates[type]; +} + +status_t EmulatedFakeCamera3::processCaptureRequest( + camera3_capture_request *request) { + + Mutex::Autolock l(mLock); + status_t res; + + /** Validation */ + + if (mStatus < STATUS_READY) { + ALOGE("%s: Can't submit capture requests in state %d", __FUNCTION__, + mStatus); + return INVALID_OPERATION; + } + + if (request == NULL) { + ALOGE("%s: NULL request!", __FUNCTION__); + return BAD_VALUE; + } + + uint32_t frameNumber = request->frame_number; + + if (request->settings == NULL && mPrevSettings.isEmpty()) { + ALOGE("%s: Request %d: NULL settings for first request after" + "configureStreams()", __FUNCTION__, frameNumber); + return BAD_VALUE; + } + + if (request->input_buffer != NULL && + request->input_buffer->stream != mInputStream) { + ALOGE("%s: Request %d: Input buffer not from input stream!", + __FUNCTION__, frameNumber); + return BAD_VALUE; + } + + if (request->num_output_buffers < 1 || request->output_buffers == NULL) { + ALOGE("%s: Request %d: No output buffers provided!", + __FUNCTION__, frameNumber); + return BAD_VALUE; + } + + // Validate all buffers, starting with input buffer if it's given + + ssize_t idx; + const camera3_stream_buffer_t *b; + if (request->input_buffer != NULL) { + idx = -1; + b = request->input_buffer; + } else { + idx = 0; + b = request->output_buffers; + } + do { + PrivateStreamInfo *priv = + static_cast<PrivateStreamInfo*>(b->stream->priv); + if (priv == NULL) { + ALOGE("%s: Request %d: Buffer %d: Unconfigured stream!", + __FUNCTION__, frameNumber, idx); + return BAD_VALUE; + } + if (!priv->alive || !priv->registered) { + ALOGE("%s: Request %d: Buffer %d: Unregistered or dead stream!", + __FUNCTION__, frameNumber, idx); + return BAD_VALUE; + } + if (b->status != CAMERA3_BUFFER_STATUS_OK) { + ALOGE("%s: Request %d: Buffer %d: Status not OK!", + __FUNCTION__, frameNumber, idx); + return BAD_VALUE; + } + if (b->release_fence != -1) { + ALOGE("%s: Request %d: Buffer %d: Has a release fence!", + __FUNCTION__, frameNumber, idx); + return BAD_VALUE; + } + if (b->buffer == NULL) { + ALOGE("%s: Request %d: Buffer %d: NULL buffer handle!", + __FUNCTION__, frameNumber, idx); + return BAD_VALUE; + } + idx++; + b = &(request->output_buffers[idx]); + } while (idx < (ssize_t)request->num_output_buffers); + + // TODO: Validate settings parameters + + /** + * Start processing this request + */ + + mStatus = STATUS_ACTIVE; + + CameraMetadata settings; + + if (request->settings == NULL) { + settings.acquire(mPrevSettings); + } else { + settings = request->settings; + } + + // TODO: Apply 3A overrides + + // TODO: Handle reprocessing + + /** + * Get ready for sensor config + */ + + nsecs_t exposureTime; + nsecs_t frameDuration; + uint32_t sensitivity; + + exposureTime = settings.find(ANDROID_SENSOR_EXPOSURE_TIME).data.i64[0]; + frameDuration = settings.find(ANDROID_SENSOR_FRAME_DURATION).data.i64[0]; + sensitivity = settings.find(ANDROID_SENSOR_SENSITIVITY).data.i32[0]; + + Buffers *sensorBuffers = new Buffers(); + Vector<camera3_stream_buffer> *buffers = new Vector<camera3_stream_buffer>(); + + sensorBuffers->setCapacity(request->num_output_buffers); + buffers->setCapacity(request->num_output_buffers); + + // Process all the buffers we got for output, constructing internal buffer + // structures for them, and lock them for writing. + for (size_t i = 0; i < request->num_output_buffers; i++) { + const camera3_stream_buffer &srcBuf = request->output_buffers[i]; + const cb_handle_t *privBuffer = + static_cast<const cb_handle_t*>(*srcBuf.buffer); + StreamBuffer destBuf; + destBuf.streamId = 0; + destBuf.width = srcBuf.stream->width; + destBuf.height = srcBuf.stream->height; + destBuf.format = privBuffer->format; // Use real private format + destBuf.stride = srcBuf.stream->width; // TODO: query from gralloc + destBuf.buffer = srcBuf.buffer; + + // Wait on fence + sp<Fence> bufferAcquireFence = new Fence(srcBuf.acquire_fence); + res = bufferAcquireFence->wait(kFenceTimeoutMs); + if (res == TIMED_OUT) { + ALOGE("%s: Request %d: Buffer %d: Fence timed out after %d ms", + __FUNCTION__, frameNumber, i, kFenceTimeoutMs); + } + if (res == OK) { + // Lock buffer for writing + const Rect rect(destBuf.width, destBuf.height); + res = GraphicBufferMapper::get().lock(*(destBuf.buffer), + GRALLOC_USAGE_HW_CAMERA_WRITE, rect, (void**)&(destBuf.img)); + if (res != OK) { + ALOGE("%s: Request %d: Buffer %d: Unable to lock buffer", + __FUNCTION__, frameNumber, i); + } + } + + if (res != OK) { + // Either waiting or locking failed. Unlock locked buffers and bail out. + for (size_t j = 0; j < i; j++) { + GraphicBufferMapper::get().unlock( + *(request->output_buffers[i].buffer)); + } + return NO_INIT; + } + + sensorBuffers->push_back(destBuf); + buffers->push_back(srcBuf); + } + + /** + * Wait until the in-flight queue has room + */ + res = mReadoutThread->waitForReadout(); + if (res != OK) { + return NO_INIT; + } + + /** + * Wait until sensor's ready. This waits for lengthy amounts of time with + * mLock held, but the interface spec is that no other calls may by done to + * the HAL by the framework while process_capture_request is happening. + */ + int syncTimeoutCount = 0; + while(!mSensor->waitForVSync(kSyncWaitTimeout)) { + if (mStatus == STATUS_ERROR) { + return NO_INIT; + } + if (syncTimeoutCount == kMaxSyncTimeoutCount) { + ALOGE("%s: Request %d: Sensor sync timed out after %lld ms", + __FUNCTION__, frameNumber, + kSyncWaitTimeout * kMaxSyncTimeoutCount / 1000000); + return NO_INIT; + } + syncTimeoutCount++; + } + + /** + * Configure sensor and queue up the request to the readout thread + */ + mSensor->setExposureTime(exposureTime); + mSensor->setFrameDuration(frameDuration); + mSensor->setSensitivity(sensitivity); + mSensor->setDestinationBuffers(sensorBuffers); + + ReadoutThread::Request r; + r.frameNumber = request->frame_number; + r.settings = settings; + r.sensorBuffers = sensorBuffers; + r.buffers = buffers; + + mReadoutThread->queueCaptureRequest(r); + + // Cache the settings for next time + mPrevSettings.acquire(settings); + + return OK; +} + +/** Debug methods */ + +void EmulatedFakeCamera3::dump(int fd) { + +} + +/** Tag query methods */ +const char* EmulatedFakeCamera3::getVendorSectionName(uint32_t tag) { + return NULL; +} + +const char* EmulatedFakeCamera3::getVendorTagName(uint32_t tag) { + return NULL; +} + +int EmulatedFakeCamera3::getVendorTagType(uint32_t tag) { + return 0; +} + +/** + * Private methods + */ + +status_t EmulatedFakeCamera3::constructStaticInfo() { + + CameraMetadata info; + // android.lens + + // 5 cm min focus distance for back camera, infinity (fixed focus) for front + const float minFocusDistance = mFacingBack ? 1.0/0.05 : 0.0; + info.update(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE, + &minFocusDistance, 1); + + // 5 m hyperfocal distance for back camera, infinity (fixed focus) for front + const float hyperFocalDistance = mFacingBack ? 1.0/5.0 : 0.0; + info.update(ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE, + &minFocusDistance, 1); + + static const float focalLength = 3.30f; // mm + info.update(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, + &focalLength, 1); + static const float aperture = 2.8f; + info.update(ANDROID_LENS_INFO_AVAILABLE_APERTURES, + &aperture, 1); + static const float filterDensity = 0; + info.update(ANDROID_LENS_INFO_AVAILABLE_FILTER_DENSITIES, + &filterDensity, 1); + static const uint8_t availableOpticalStabilization = + ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF; + info.update(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION, + &availableOpticalStabilization, 1); + + static const int32_t lensShadingMapSize[] = {1, 1}; + info.update(ANDROID_LENS_INFO_SHADING_MAP_SIZE, lensShadingMapSize, + sizeof(lensShadingMapSize)/sizeof(int32_t)); + + static const float lensShadingMap[3 * 1 * 1 ] = + { 1.f, 1.f, 1.f }; + info.update(ANDROID_LENS_INFO_SHADING_MAP, lensShadingMap, + sizeof(lensShadingMap)/sizeof(float)); + + // Identity transform + static const int32_t geometricCorrectionMapSize[] = {2, 2}; + info.update(ANDROID_LENS_INFO_GEOMETRIC_CORRECTION_MAP_SIZE, + geometricCorrectionMapSize, + sizeof(geometricCorrectionMapSize)/sizeof(int32_t)); + + static const float geometricCorrectionMap[2 * 3 * 2 * 2] = { + 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, + 1.f, 0.f, 1.f, 0.f, 1.f, 0.f, + 0.f, 1.f, 0.f, 1.f, 0.f, 1.f, + 1.f, 1.f, 1.f, 1.f, 1.f, 1.f}; + info.update(ANDROID_LENS_INFO_GEOMETRIC_CORRECTION_MAP, + geometricCorrectionMap, + sizeof(geometricCorrectionMap)/sizeof(float)); + + uint8_t lensFacing = mFacingBack ? + ANDROID_LENS_FACING_BACK : ANDROID_LENS_FACING_FRONT; + info.update(ANDROID_LENS_FACING, &lensFacing, 1); + + float lensPosition[3]; + if (mFacingBack) { + // Back-facing camera is center-top on device + lensPosition[0] = 0; + lensPosition[1] = 20; + lensPosition[2] = -5; + } else { + // Front-facing camera is center-right on device + lensPosition[0] = 20; + lensPosition[1] = 20; + lensPosition[2] = 0; + } + info.update(ANDROID_LENS_POSITION, lensPosition, sizeof(lensPosition)/ + sizeof(float)); + + // android.sensor + + info.update(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE, + Sensor::kExposureTimeRange, 2); + + info.update(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION, + &Sensor::kFrameDurationRange[1], 1); + + info.update(ANDROID_SENSOR_INFO_AVAILABLE_SENSITIVITIES, + (int32_t*)Sensor::kAvailableSensitivities, + sizeof(Sensor::kAvailableSensitivities) + /sizeof(uint32_t)); + + info.update(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT, + &Sensor::kColorFilterArrangement, 1); + + static const float sensorPhysicalSize[2] = {3.20f, 2.40f}; // mm + info.update(ANDROID_SENSOR_INFO_PHYSICAL_SIZE, + sensorPhysicalSize, 2); + + info.update(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, + (int32_t*)Sensor::kResolution, 2); + + info.update(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, + (int32_t*)Sensor::kResolution, 2); + + info.update(ANDROID_SENSOR_INFO_WHITE_LEVEL, + (int32_t*)&Sensor::kMaxRawValue, 1); + + static const int32_t blackLevelPattern[4] = { + (int32_t)Sensor::kBlackLevel, (int32_t)Sensor::kBlackLevel, + (int32_t)Sensor::kBlackLevel, (int32_t)Sensor::kBlackLevel + }; + info.update(ANDROID_SENSOR_BLACK_LEVEL_PATTERN, + blackLevelPattern, sizeof(blackLevelPattern)/sizeof(int32_t)); + + //TODO: sensor color calibration fields + + // android.flash + static const uint8_t flashAvailable = 0; + info.update(ANDROID_FLASH_INFO_AVAILABLE, &flashAvailable, 1); + + static const int64_t flashChargeDuration = 0; + info.update(ANDROID_FLASH_INFO_CHARGE_DURATION, &flashChargeDuration, 1); + + // android.tonemap + + static const int32_t tonemapCurvePoints = 128; + info.update(ANDROID_TONEMAP_MAX_CURVE_POINTS, &tonemapCurvePoints, 1); + + // android.scaler + + info.update(ANDROID_SCALER_AVAILABLE_FORMATS, + (int32_t*)kAvailableFormats, + sizeof(kAvailableFormats)/sizeof(uint32_t)); + + info.update(ANDROID_SCALER_AVAILABLE_RAW_SIZES, + (int32_t*)kAvailableRawSizes, + sizeof(kAvailableRawSizes)/sizeof(uint32_t)); + + info.update(ANDROID_SCALER_AVAILABLE_RAW_MIN_DURATIONS, + (int64_t*)kAvailableRawMinDurations, + sizeof(kAvailableRawMinDurations)/sizeof(uint64_t)); + + if (mFacingBack) { + info.update(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES, + (int32_t*)kAvailableProcessedSizesBack, + sizeof(kAvailableProcessedSizesBack)/sizeof(uint32_t)); + } else { + info.update(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES, + (int32_t*)kAvailableProcessedSizesFront, + sizeof(kAvailableProcessedSizesFront)/sizeof(uint32_t)); + } + + info.update(ANDROID_SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS, + (int64_t*)kAvailableProcessedMinDurations, + sizeof(kAvailableProcessedMinDurations)/sizeof(uint64_t)); + + if (mFacingBack) { + info.update(ANDROID_SCALER_AVAILABLE_JPEG_SIZES, + (int32_t*)kAvailableJpegSizesBack, + sizeof(kAvailableJpegSizesBack)/sizeof(uint32_t)); + } else { + info.update(ANDROID_SCALER_AVAILABLE_JPEG_SIZES, + (int32_t*)kAvailableJpegSizesFront, + sizeof(kAvailableJpegSizesFront)/sizeof(uint32_t)); + } + + info.update(ANDROID_SCALER_AVAILABLE_JPEG_MIN_DURATIONS, + (int64_t*)kAvailableJpegMinDurations, + sizeof(kAvailableJpegMinDurations)/sizeof(uint64_t)); + + static const int32_t maxZoom = 10; + info.update(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, + &maxZoom, 1); + + // android.jpeg + + static const int32_t jpegThumbnailSizes[] = { + 0, 0, + 160, 120, + 320, 240 + }; + info.update(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, + jpegThumbnailSizes, sizeof(jpegThumbnailSizes)/sizeof(int32_t)); + + static const int32_t jpegMaxSize = JpegCompressor::kMaxJpegSize; + info.update(ANDROID_JPEG_MAX_SIZE, &jpegMaxSize, 1); + + // android.stats + + static const uint8_t availableFaceDetectModes[] = { + ANDROID_STATISTICS_FACE_DETECT_MODE_OFF, + ANDROID_STATISTICS_FACE_DETECT_MODE_SIMPLE, + ANDROID_STATISTICS_FACE_DETECT_MODE_FULL + }; + + info.update(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES, + availableFaceDetectModes, + sizeof(availableFaceDetectModes)); + + static const int32_t maxFaceCount = 8; + info.update(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, + &maxFaceCount, 1); + + static const int32_t histogramSize = 64; + info.update(ANDROID_STATISTICS_INFO_HISTOGRAM_BUCKET_COUNT, + &histogramSize, 1); + + static const int32_t maxHistogramCount = 1000; + info.update(ANDROID_STATISTICS_INFO_MAX_HISTOGRAM_COUNT, + &maxHistogramCount, 1); + + static const int32_t sharpnessMapSize[2] = {64, 64}; + info.update(ANDROID_STATISTICS_INFO_SHARPNESS_MAP_SIZE, + sharpnessMapSize, sizeof(sharpnessMapSize)/sizeof(int32_t)); + + static const int32_t maxSharpnessMapValue = 1000; + info.update(ANDROID_STATISTICS_INFO_MAX_SHARPNESS_MAP_VALUE, + &maxSharpnessMapValue, 1); + + // android.control + + static const uint8_t availableSceneModes[] = { + ANDROID_CONTROL_SCENE_MODE_UNSUPPORTED + }; + info.update(ANDROID_CONTROL_AVAILABLE_SCENE_MODES, + availableSceneModes, sizeof(availableSceneModes)); + + static const uint8_t availableEffects[] = { + ANDROID_CONTROL_EFFECT_MODE_OFF + }; + info.update(ANDROID_CONTROL_AVAILABLE_EFFECTS, + availableEffects, sizeof(availableEffects)); + + int32_t max3aRegions = 0; + info.update(ANDROID_CONTROL_MAX_REGIONS, + &max3aRegions, 1); + + static const uint8_t availableAeModes[] = { + ANDROID_CONTROL_AE_MODE_OFF, + ANDROID_CONTROL_AE_MODE_ON + }; + info.update(ANDROID_CONTROL_AE_AVAILABLE_MODES, + availableAeModes, sizeof(availableAeModes)); + + static const camera_metadata_rational exposureCompensationStep = { + 1, 3 + }; + info.update(ANDROID_CONTROL_AE_COMPENSATION_STEP, + &exposureCompensationStep, 1); + + int32_t exposureCompensationRange[] = {-9, 9}; + info.update(ANDROID_CONTROL_AE_COMPENSATION_RANGE, + exposureCompensationRange, + sizeof(exposureCompensationRange)/sizeof(int32_t)); + + static const int32_t availableTargetFpsRanges[] = { + 5, 30, 15, 30 + }; + info.update(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, + availableTargetFpsRanges, + sizeof(availableTargetFpsRanges)/sizeof(int32_t)); + + static const uint8_t availableAntibandingModes[] = { + ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF, + ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO + }; + info.update(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES, + availableAntibandingModes, sizeof(availableAntibandingModes)); + + static const uint8_t availableAwbModes[] = { + ANDROID_CONTROL_AWB_MODE_OFF, + ANDROID_CONTROL_AWB_MODE_AUTO, + ANDROID_CONTROL_AWB_MODE_INCANDESCENT, + ANDROID_CONTROL_AWB_MODE_FLUORESCENT, + ANDROID_CONTROL_AWB_MODE_DAYLIGHT, + ANDROID_CONTROL_AWB_MODE_SHADE + }; + info.update(ANDROID_CONTROL_AWB_AVAILABLE_MODES, + availableAwbModes, sizeof(availableAwbModes)); + + static const uint8_t availableAfModesBack[] = { + ANDROID_CONTROL_AF_MODE_OFF, + ANDROID_CONTROL_AF_MODE_AUTO, + ANDROID_CONTROL_AF_MODE_MACRO, + ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO, + ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE + }; + + static const uint8_t availableAfModesFront[] = { + ANDROID_CONTROL_AF_MODE_OFF + }; + + if (mFacingBack) { + info.update(ANDROID_CONTROL_AF_AVAILABLE_MODES, + availableAfModesBack, sizeof(availableAfModesBack)); + } else { + info.update(ANDROID_CONTROL_AF_AVAILABLE_MODES, + availableAfModesFront, sizeof(availableAfModesFront)); + } + + static const uint8_t availableVstabModes[] = { + ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF + }; + info.update(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES, + availableVstabModes, sizeof(availableVstabModes)); + + mCameraInfo = info.release(); + + return OK; +} + +void EmulatedFakeCamera3::signalReadoutIdle() { + Mutex::Autolock l(mLock); + // Need to chek isIdle again because waiting on mLock may have allowed + // something to be placed in the in-flight queue. + if (mStatus == STATUS_ACTIVE && mReadoutThread->isIdle()) { + ALOGV("Now idle"); + mStatus = STATUS_READY; + } +} + +EmulatedFakeCamera3::ReadoutThread::ReadoutThread(EmulatedFakeCamera3 *parent) : + mParent(parent) { +} + +EmulatedFakeCamera3::ReadoutThread::~ReadoutThread() { + for (List<Request>::iterator i = mInFlightQueue.begin(); + i != mInFlightQueue.end(); i++) { + delete i->buffers; + delete i->sensorBuffers; + } +} + +void EmulatedFakeCamera3::ReadoutThread::queueCaptureRequest(const Request &r) { + Mutex::Autolock l(mLock); + + mInFlightQueue.push_back(r); + mInFlightSignal.signal(); +} + +bool EmulatedFakeCamera3::ReadoutThread::isIdle() { + Mutex::Autolock l(mLock); + return mInFlightQueue.empty() && !mThreadActive; +} + +status_t EmulatedFakeCamera3::ReadoutThread::waitForReadout() { + status_t res; + Mutex::Autolock l(mLock); + int loopCount = 0; + while (mInFlightQueue.size() >= kMaxQueueSize) { + res = mInFlightSignal.waitRelative(mLock, kWaitPerLoop); + if (res != OK && res != TIMED_OUT) { + ALOGE("%s: Error waiting for in-flight queue to shrink", + __FUNCTION__); + return INVALID_OPERATION; + } + if (loopCount == kMaxWaitLoops) { + ALOGE("%s: Timed out waiting for in-flight queue to shrink", + __FUNCTION__); + return TIMED_OUT; + } + loopCount++; + } + return OK; +} + +bool EmulatedFakeCamera3::ReadoutThread::threadLoop() { + status_t res; + + // First wait for a request from the in-flight queue + + if (mCurrentRequest.settings.isEmpty()) { + Mutex::Autolock l(mLock); + if (mInFlightQueue.empty()) { + res = mInFlightSignal.waitRelative(mLock, kWaitPerLoop); + if (res == TIMED_OUT) { + return true; + } else if (res != NO_ERROR) { + ALOGE("%s: Error waiting for capture requests: %d", + __FUNCTION__, res); + return false; + } + } + mCurrentRequest.frameNumber = mInFlightQueue.begin()->frameNumber; + mCurrentRequest.settings.acquire(mInFlightQueue.begin()->settings); + mCurrentRequest.buffers = mInFlightQueue.begin()->buffers; + mCurrentRequest.sensorBuffers = mInFlightQueue.begin()->sensorBuffers; + mInFlightQueue.erase(mInFlightQueue.begin()); + mInFlightSignal.signal(); + mThreadActive = true; + } + + // Then wait for it to be delivered from the sensor + + nsecs_t captureTime; + bool gotFrame = + mParent->mSensor->waitForNewFrame(kWaitPerLoop, &captureTime); + if (!gotFrame) return true; + + // Got everything, construct result + + camera3_capture_result result; + + mCurrentRequest.settings.update(ANDROID_SENSOR_TIMESTAMP, + &captureTime, 1); + + for (size_t i = 0; i < mCurrentRequest.buffers->size(); i++) { + camera3_stream_buffer &buf = mCurrentRequest.buffers->editItemAt(i); + + GraphicBufferMapper::get().unlock(*buf.buffer); + + buf.status = CAMERA3_BUFFER_STATUS_OK; + buf.acquire_fence = -1; + buf.release_fence = -1; + } + + result.frame_number = mCurrentRequest.frameNumber; + result.result = mCurrentRequest.settings.getAndLock(); + result.num_output_buffers = mCurrentRequest.buffers->size(); + result.output_buffers = mCurrentRequest.buffers->array(); + + // Go idle if queue is empty, before sending result + bool signalIdle = false; + { + Mutex::Autolock l(mLock); + if (mInFlightQueue.empty()) { + mThreadActive = false; + signalIdle = true; + } + } + if (signalIdle) mParent->signalReadoutIdle(); + + // Send it off to the framework + + mParent->sendCaptureResult(&result); + + // Clean up + mCurrentRequest.settings.unlock(result.result); + + delete mCurrentRequest.buffers; + mCurrentRequest.buffers = NULL; + delete mCurrentRequest.sensorBuffers; + mCurrentRequest.sensorBuffers = NULL; + mCurrentRequest.settings.clear(); + + return true; +} + + +}; // namespace android diff --git a/camera/EmulatedFakeCamera3.h b/camera/EmulatedFakeCamera3.h new file mode 100644 index 0000000..74f8496 --- /dev/null +++ b/camera/EmulatedFakeCamera3.h @@ -0,0 +1,211 @@ +/* + * 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 HW_EMULATOR_CAMERA_EMULATED_FAKE_CAMERA3_H +#define HW_EMULATOR_CAMERA_EMULATED_FAKE_CAMERA3_H + +/** + * Contains declaration of a class EmulatedCamera that encapsulates + * functionality of a fake camera that implements version 3 of the camera device + * interace. + */ + +#include "EmulatedCamera3.h" +#include "fake-pipeline2/Base.h" +#include "fake-pipeline2/Sensor.h" +#include "fake-pipeline2/JpegCompressor.h" +#include <camera/CameraMetadata.h> +#include <utils/List.h> +#include <utils/Mutex.h> + +namespace android { + +/* Encapsulates functionality common to all version 3.0 emulated camera devices + * + * Note that EmulatedCameraFactory instantiates an object of this class just + * once, when EmulatedCameraFactory instance gets constructed. Connection to / + * disconnection from the actual camera device is handled by calls to + * connectDevice(), and closeCamera() methods of this class that are invoked in + * response to hw_module_methods_t::open, and camera_device::close callbacks. + */ +class EmulatedFakeCamera3 : public EmulatedCamera3 { +public: + + EmulatedFakeCamera3(int cameraId, bool facingBack, + struct hw_module_t* module); + + virtual ~EmulatedFakeCamera3(); + + /**************************************************************************** + * EmulatedCamera3 virtual overrides + ***************************************************************************/ + +public: + + virtual status_t Initialize(); + + /**************************************************************************** + * Camera module API and generic hardware device API implementation + ***************************************************************************/ + +public: + virtual status_t connectCamera(hw_device_t** device); + + virtual status_t closeCamera(); + + virtual status_t getCameraInfo(struct camera_info *info); + + /**************************************************************************** + * EmualtedCamera3 abstract API implementation + ***************************************************************************/ + +protected: + + virtual status_t configureStreams( + camera3_stream_configuration *streamList); + + virtual status_t registerStreamBuffers( + const camera3_stream_buffer_set *bufferSet) ; + + virtual const camera_metadata_t* constructDefaultRequestSettings( + int type); + + virtual status_t processCaptureRequest(camera3_capture_request *request); + + /** Debug methods */ + + virtual void dump(int fd); + + /** Tag query methods */ + virtual const char *getVendorSectionName(uint32_t tag); + + virtual const char *getVendorTagName(uint32_t tag); + + virtual int getVendorTagType(uint32_t tag); + +private: + + status_t constructStaticInfo(); + + /** Signal from readout thread that it doesn't have anything to do */ + void signalReadoutIdle(); + + /**************************************************************************** + * Static configuration information + ***************************************************************************/ +private: + static const uint32_t kMaxRawStreamCount = 1; + static const uint32_t kMaxProcessedStreamCount = 3; + static const uint32_t kMaxJpegStreamCount = 1; + static const uint32_t kMaxReprocessStreamCount = 2; + static const uint32_t kMaxBufferCount = 4; + static const uint32_t kAvailableFormats[]; + static const uint32_t kAvailableRawSizes[]; + static const uint64_t kAvailableRawMinDurations[]; + static const uint32_t kAvailableProcessedSizesBack[]; + static const uint32_t kAvailableProcessedSizesFront[]; + static const uint64_t kAvailableProcessedMinDurations[]; + static const uint32_t kAvailableJpegSizesBack[]; + static const uint32_t kAvailableJpegSizesFront[]; + static const uint64_t kAvailableJpegMinDurations[]; + + static const int64_t kSyncWaitTimeout = 10000000; // 10 ms + static const int32_t kMaxSyncTimeoutCount = 1000; // 1000 kSyncWaitTimeouts + static const uint32_t kFenceTimeoutMs = 2000; // 2 s + + /**************************************************************************** + * Data members. + ***************************************************************************/ + + /* HAL interface serialization lock. */ + Mutex mLock; + + /* Facing back (true) or front (false) switch. */ + bool mFacingBack; + + /** + * Cache for default templates. Once one is requested, the pointer must be + * valid at least until close() is called on the device + */ + camera_metadata_t *mDefaultTemplates[CAMERA3_TEMPLATE_COUNT]; + + /** + * Private stream information, stored in camera3_stream_t->priv. + */ + struct PrivateStreamInfo { + bool alive; + bool registered; + }; + + // Shortcut to the input stream + camera3_stream_t* mInputStream; + + // All streams, including input stream + List<camera3_stream_t*> mStreams; + + typedef List<camera3_stream_t*>::iterator StreamIterator; + + // Cached settings from latest submitted request + CameraMetadata mPrevSettings; + + /** Fake hardware interfaces */ + sp<Sensor> mSensor; + sp<JpegCompressor> mJpegCompressor; + + /** Processing thread for sending out results */ + + class ReadoutThread : public Thread { + public: + ReadoutThread(EmulatedFakeCamera3 *parent); + ~ReadoutThread(); + + struct Request { + uint32_t frameNumber; + CameraMetadata settings; + Vector<camera3_stream_buffer> *buffers; + Buffers *sensorBuffers; + }; + + void queueCaptureRequest(const Request &r); + bool isIdle(); + status_t waitForReadout(); + + private: + static const nsecs_t kWaitPerLoop = 10000000L; // 10 ms + static const nsecs_t kMaxWaitLoops = 1000; + static const size_t kMaxQueueSize = 2; + + EmulatedFakeCamera3 *mParent; + Mutex mLock; + + List<Request> mInFlightQueue; + Condition mInFlightSignal; + bool mThreadActive; + + virtual bool threadLoop(); + + // Only accessed by threadLoop + + Request mCurrentRequest; + + }; + + sp<ReadoutThread> mReadoutThread; +}; + +} // namespace android + +#endif // HW_EMULATOR_CAMERA_EMULATED_CAMERA3_H diff --git a/camera/fake-pipeline2/Sensor.cpp b/camera/fake-pipeline2/Sensor.cpp index 316fe02..0c12f6f 100644 --- a/camera/fake-pipeline2/Sensor.cpp +++ b/camera/fake-pipeline2/Sensor.cpp @@ -100,9 +100,8 @@ float sqrtf_approx(float r) { -Sensor::Sensor(EmulatedFakeCamera2 *parent): +Sensor::Sensor(): Thread(false), - mParent(parent), mGotVSync(false), mExposureTime(kFrameDurationRange[0]-kMinVerticalBlank), mFrameDuration(kFrameDurationRange[0]), diff --git a/camera/fake-pipeline2/Sensor.h b/camera/fake-pipeline2/Sensor.h index ce7b4ad..72128c5 100644 --- a/camera/fake-pipeline2/Sensor.h +++ b/camera/fake-pipeline2/Sensor.h @@ -87,7 +87,7 @@ class EmulatedFakeCamera2; class Sensor: private Thread, public virtual RefBase { public: - Sensor(EmulatedFakeCamera2 *parent); + Sensor(); ~Sensor(); /* @@ -172,8 +172,6 @@ class Sensor: private Thread, public virtual RefBase { static const uint32_t kDefaultSensitivity; private: - EmulatedFakeCamera2 *mParent; - Mutex mControlMutex; // Lock before accessing control parameters // Start of control parameters Condition mVSync; |
