summaryrefslogtreecommitdiffstats
path: root/services/camera/libcameraservice/Camera2Device.cpp
diff options
context:
space:
mode:
authorEino-Ville Talvala <etalvala@google.com>2012-05-20 15:59:14 -0700
committerEino-Ville Talvala <etalvala@google.com>2012-05-29 13:47:50 -0700
commitf69c70ded4316ea3ee504ac779bd024433ed4ef7 (patch)
tree35a9f7b23fff4fb40321cf4c009d268bed27bea8 /services/camera/libcameraservice/Camera2Device.cpp
parentdd72c3017aef65d099460cfc6c0402bc2ba85bc3 (diff)
downloadframeworks_av-f69c70ded4316ea3ee504ac779bd024433ed4ef7.zip
frameworks_av-f69c70ded4316ea3ee504ac779bd024433ed4ef7.tar.gz
frameworks_av-f69c70ded4316ea3ee504ac779bd024433ed4ef7.tar.bz2
Camera service: Initialization for camera2 clients and devices
- Refactor initialization code to hide device type from CameraService - Add metadata queue class to Camera2Device - Initialization of Camera2Device, Camera2Client - Conversion from HAL2 device static metadata to camera API parameters. Bug: 6243944 Change-Id: I524145b45438e906d8493dae202704ce8f090aeb
Diffstat (limited to 'services/camera/libcameraservice/Camera2Device.cpp')
-rw-r--r--services/camera/libcameraservice/Camera2Device.cpp295
1 files changed, 285 insertions, 10 deletions
diff --git a/services/camera/libcameraservice/Camera2Device.cpp b/services/camera/libcameraservice/Camera2Device.cpp
index ff5b057..4b0cfc4 100644
--- a/services/camera/libcameraservice/Camera2Device.cpp
+++ b/services/camera/libcameraservice/Camera2Device.cpp
@@ -22,8 +22,8 @@
namespace android {
-Camera2Device::Camera2Device(const char *name):
- mName(name),
+Camera2Device::Camera2Device(int id):
+ mId(id),
mDevice(NULL)
{
@@ -35,32 +35,307 @@ Camera2Device::~Camera2Device()
status_t res;
res = mDevice->common.close(&mDevice->common);
if (res != OK) {
- ALOGE("Could not close camera2 %s: %s (%d)",
- mName, strerror(-res), res);
+ ALOGE("%s: Could not close camera %d: %s (%d)",
+ __FUNCTION__,
+ mId, strerror(-res), res);
}
+ mDevice = NULL;
}
}
-status_t Camera2Device::initialize(hw_module_t *module)
+status_t Camera2Device::initialize(camera_module_t *module)
{
status_t res;
- res = module->methods->open(module, mName,
+ char name[10];
+ snprintf(name, sizeof(name), "%d", mId);
+
+ res = module->common.methods->open(&module->common, name,
reinterpret_cast<hw_device_t**>(&mDevice));
if (res != OK) {
- ALOGE("Could not open camera %s: %s (%d)", mName, strerror(-res), res);
+ ALOGE("%s: Could not open camera %d: %s (%d)", __FUNCTION__,
+ mId, strerror(-res), res);
return res;
}
if (mDevice->common.version != CAMERA_DEVICE_API_VERSION_2_0) {
- ALOGE("Could not open camera %s: "
- "Camera device is not version 2.0, reports %x instead",
- mName, mDevice->common.version);
+ ALOGE("%s: Could not open camera %d: "
+ "Camera device is not version %x, reports %x instead",
+ __FUNCTION__, mId, CAMERA_DEVICE_API_VERSION_2_0,
+ mDevice->common.version);
return BAD_VALUE;
}
+ camera_info info;
+ res = module->get_camera_info(mId, &info);
+ if (res != OK ) return res;
+
+ if (info.device_version != mDevice->common.version) {
+ ALOGE("%s: HAL reporting mismatched camera_info version (%x)"
+ " and device version (%x).", __FUNCTION__,
+ mDevice->common.version, info.device_version);
+ return BAD_VALUE;
+ }
+
+ mDeviceInfo = info.static_camera_characteristics;
+
+ res = mDevice->ops->set_request_queue_src_ops(mDevice,
+ mRequestQueue.getToConsumerInterface());
+ if (res != OK) return res;
+
+ res = mDevice->ops->set_frame_queue_dst_ops(mDevice,
+ mFrameQueue.getToProducerInterface());
+ if (res != OK) return res;
+
+ res = mDevice->ops->get_metadata_vendor_tag_ops(mDevice, &mVendorTagOps);
+ if (res != OK ) return res;
+
+ return OK;
+}
+
+status_t Camera2Device::setStreamingRequest(camera_metadata_t* request)
+{
+ mRequestQueue.setStreamSlot(request);
+ return OK;
+}
+
+/**
+ * Camera2Device::MetadataQueue
+ */
+
+Camera2Device::MetadataQueue::MetadataQueue():
+ mDevice(NULL),
+ mFrameCount(0),
+ mCount(0),
+ mStreamSlotCount(0),
+ mSignalConsumer(true)
+{
+ camera2_request_queue_src_ops::dequeue_request = consumer_dequeue;
+ camera2_request_queue_src_ops::request_count = consumer_buffer_count;
+ camera2_request_queue_src_ops::free_request = consumer_free;
+
+ camera2_frame_queue_dst_ops::dequeue_frame = producer_dequeue;
+ camera2_frame_queue_dst_ops::cancel_frame = producer_cancel;
+ camera2_frame_queue_dst_ops::enqueue_frame = producer_enqueue;
+}
+
+Camera2Device::MetadataQueue::~MetadataQueue() {
+ Mutex::Autolock l(mMutex);
+ freeBuffers(mEntries.begin(), mEntries.end());
+ freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
+}
+
+// Interface to camera2 HAL as consumer (input requests/reprocessing)
+const camera2_request_queue_src_ops_t*
+Camera2Device::MetadataQueue::getToConsumerInterface() {
+ return static_cast<camera2_request_queue_src_ops_t*>(this);
+}
+
+void Camera2Device::MetadataQueue::setFromConsumerInterface(camera2_device_t *d) {
+ Mutex::Autolock l(mMutex);
+ mDevice = d;
+}
+
+const camera2_frame_queue_dst_ops_t*
+Camera2Device::MetadataQueue::getToProducerInterface() {
+ return static_cast<camera2_frame_queue_dst_ops_t*>(this);
+}
+
+// Real interfaces
+status_t Camera2Device::MetadataQueue::enqueue(camera_metadata_t *buf) {
+ Mutex::Autolock l(mMutex);
+
+ mCount++;
+ mEntries.push_back(buf);
+ notEmpty.signal();
+
+ if (mSignalConsumer && mDevice != NULL) {
+ mSignalConsumer = false;
+
+ mMutex.unlock();
+ ALOGV("%s: Signaling consumer", __FUNCTION__);
+ mDevice->ops->notify_request_queue_not_empty(mDevice);
+ mMutex.lock();
+ }
+ return OK;
+}
+
+int Camera2Device::MetadataQueue::getBufferCount() {
+ Mutex::Autolock l(mMutex);
+ if (mStreamSlotCount > 0) {
+ return CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS;
+ }
+ return mCount;
+}
+
+status_t Camera2Device::MetadataQueue::dequeue(camera_metadata_t **buf,
+ bool incrementCount)
+{
+ Mutex::Autolock l(mMutex);
+
+ if (mCount == 0) {
+ if (mStreamSlotCount == 0) {
+ ALOGV("%s: Empty", __FUNCTION__);
+ *buf = NULL;
+ mSignalConsumer = true;
+ return OK;
+ }
+ ALOGV("%s: Streaming %d frames to queue", __FUNCTION__,
+ mStreamSlotCount);
+
+ for (List<camera_metadata_t*>::iterator slotEntry = mStreamSlot.begin();
+ slotEntry != mStreamSlot.end();
+ slotEntry++ ) {
+ size_t entries = get_camera_metadata_entry_count(*slotEntry);
+ size_t dataBytes = get_camera_metadata_data_count(*slotEntry);
+
+ camera_metadata_t *copy =
+ allocate_camera_metadata(entries, dataBytes);
+ append_camera_metadata(copy, *slotEntry);
+ mEntries.push_back(copy);
+ }
+ mCount = mStreamSlotCount;
+ }
+ ALOGV("MetadataQueue: deque (%d buffers)", mCount);
+ camera_metadata_t *b = *(mEntries.begin());
+ mEntries.erase(mEntries.begin());
+
+ if (incrementCount) {
+ add_camera_metadata_entry(b,
+ ANDROID_REQUEST_FRAME_COUNT,
+ (void**)&mFrameCount, 1);
+ mFrameCount++;
+ }
+
+ *buf = b;
+ mCount--;
+
return OK;
}
+status_t Camera2Device::MetadataQueue::waitForBuffer(nsecs_t timeout)
+{
+ Mutex::Autolock l(mMutex);
+ status_t res;
+ while (mCount == 0) {
+ res = notEmpty.waitRelative(mMutex,timeout);
+ if (res != OK) return res;
+ }
+ return OK;
+}
+
+status_t Camera2Device::MetadataQueue::setStreamSlot(camera_metadata_t *buf)
+{
+ Mutex::Autolock l(mMutex);
+ if (buf == NULL) {
+ freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
+ mStreamSlotCount = 0;
+ return OK;
+ }
+ if (mStreamSlotCount > 1) {
+ List<camera_metadata_t*>::iterator deleter = ++mStreamSlot.begin();
+ freeBuffers(++mStreamSlot.begin(), mStreamSlot.end());
+ mStreamSlotCount = 1;
+ }
+ if (mStreamSlotCount == 1) {
+ free_camera_metadata( *(mStreamSlot.begin()) );
+ *(mStreamSlot.begin()) = buf;
+ } else {
+ mStreamSlot.push_front(buf);
+ mStreamSlotCount = 1;
+ }
+ return OK;
+}
+
+status_t Camera2Device::MetadataQueue::setStreamSlot(
+ const List<camera_metadata_t*> &bufs)
+{
+ Mutex::Autolock l(mMutex);
+ if (mStreamSlotCount > 0) {
+ freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
+ }
+ mStreamSlot = bufs;
+ mStreamSlotCount = mStreamSlot.size();
+
+ return OK;
+}
+
+status_t Camera2Device::MetadataQueue::freeBuffers(
+ List<camera_metadata_t*>::iterator start,
+ List<camera_metadata_t*>::iterator end)
+{
+ while (start != end) {
+ free_camera_metadata(*start);
+ start = mStreamSlot.erase(start);
+ }
+ return OK;
+}
+
+Camera2Device::MetadataQueue* Camera2Device::MetadataQueue::getInstance(
+ const camera2_request_queue_src_ops_t *q)
+{
+ const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q);
+ return const_cast<MetadataQueue*>(cmq);
+}
+
+Camera2Device::MetadataQueue* Camera2Device::MetadataQueue::getInstance(
+ const camera2_frame_queue_dst_ops_t *q)
+{
+ const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q);
+ return const_cast<MetadataQueue*>(cmq);
+}
+
+int Camera2Device::MetadataQueue::consumer_buffer_count(
+ const camera2_request_queue_src_ops_t *q)
+{
+ MetadataQueue *queue = getInstance(q);
+ return queue->getBufferCount();
+}
+
+int Camera2Device::MetadataQueue::consumer_dequeue(
+ const camera2_request_queue_src_ops_t *q,
+ camera_metadata_t **buffer)
+{
+ MetadataQueue *queue = getInstance(q);
+ return queue->dequeue(buffer, true);
+}
+
+int Camera2Device::MetadataQueue::consumer_free(
+ const camera2_request_queue_src_ops_t *q,
+ camera_metadata_t *old_buffer)
+{
+ MetadataQueue *queue = getInstance(q);
+ free_camera_metadata(old_buffer);
+ return OK;
+}
+
+int Camera2Device::MetadataQueue::producer_dequeue(
+ const camera2_frame_queue_dst_ops_t *q,
+ size_t entries, size_t bytes,
+ camera_metadata_t **buffer)
+{
+ camera_metadata_t *new_buffer =
+ allocate_camera_metadata(entries, bytes);
+ if (new_buffer == NULL) return NO_MEMORY;
+ *buffer = new_buffer;
+ return OK;
+}
+
+int Camera2Device::MetadataQueue::producer_cancel(
+ const camera2_frame_queue_dst_ops_t *q,
+ camera_metadata_t *old_buffer)
+{
+ free_camera_metadata(old_buffer);
+ return OK;
+}
+
+int Camera2Device::MetadataQueue::producer_enqueue(
+ const camera2_frame_queue_dst_ops_t *q,
+ camera_metadata_t *filled_buffer)
+{
+ MetadataQueue *queue = getInstance(q);
+ return queue->enqueue(filled_buffer);
+}
+
}; // namespace android