diff options
Diffstat (limited to 'camera/BufferSourceAdapter.cpp')
-rw-r--r-- | camera/BufferSourceAdapter.cpp | 1007 |
1 files changed, 1007 insertions, 0 deletions
diff --git a/camera/BufferSourceAdapter.cpp b/camera/BufferSourceAdapter.cpp new file mode 100644 index 0000000..3c4e698 --- /dev/null +++ b/camera/BufferSourceAdapter.cpp @@ -0,0 +1,1007 @@ +/* + * Copyright (C) Texas Instruments - http://www.ti.com/ + * + * 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. + */ + +#ifdef OMAP_ENHANCEMENT_CPCAM + +#include "BufferSourceAdapter.h" +#include <ui/GraphicBuffer.h> +#include <ui/GraphicBufferMapper.h> +#include <hal_public.h> + +namespace Ti { +namespace Camera { + +static int getANWFormat(const char* parameters_format) +{ + int format = HAL_PIXEL_FORMAT_TI_NV12; + + if (parameters_format != NULL) { + if (strcmp(parameters_format, android::CameraParameters::PIXEL_FORMAT_YUV422I) == 0) { + CAMHAL_LOGDA("CbYCrY format selected"); + format = HAL_PIXEL_FORMAT_TI_UYVY; + } else if (strcmp(parameters_format, android::CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) { + CAMHAL_LOGDA("YUV420SP format selected"); + format = HAL_PIXEL_FORMAT_TI_NV12; + } else if (strcmp(parameters_format, android::CameraParameters::PIXEL_FORMAT_RGB565) == 0) { + CAMHAL_LOGDA("RGB565 format selected"); + // TODO(XXX): not defined yet + format = -1; + } else if (strcmp(parameters_format, android::CameraParameters::PIXEL_FORMAT_BAYER_RGGB) == 0) { + format = HAL_PIXEL_FORMAT_TI_Y16; + } else { + CAMHAL_LOGDA("Invalid format, NV12 format selected as default"); + format = HAL_PIXEL_FORMAT_TI_NV12; + } + } + + return format; +} + +static int getUsageFromANW(int format) +{ + int usage = GRALLOC_USAGE_SW_READ_RARELY | + GRALLOC_USAGE_SW_WRITE_NEVER; + + switch (format) { + case HAL_PIXEL_FORMAT_TI_NV12: + case HAL_PIXEL_FORMAT_TI_Y16: + case HAL_PIXEL_FORMAT_TI_UYVY: + // This usage flag indicates to gralloc we want the + // buffers to come from system heap + usage |= GRALLOC_USAGE_PRIVATE_0; + break; + default: + // No special flags needed + break; + } + return usage; +} + +static const char* getFormatFromANW(int format) +{ + switch (format) { + case HAL_PIXEL_FORMAT_TI_NV12: + // Assuming NV12 1D is RAW or Image frame + return android::CameraParameters::PIXEL_FORMAT_YUV420SP; + case HAL_PIXEL_FORMAT_TI_Y16: + return android::CameraParameters::PIXEL_FORMAT_BAYER_RGGB; + case HAL_PIXEL_FORMAT_TI_UYVY: + return android::CameraParameters::PIXEL_FORMAT_YUV422I; + default: + break; + } + return android::CameraParameters::PIXEL_FORMAT_YUV420SP; +} + +static CameraFrame::FrameType formatToOutputFrameType(const char* format) { + switch (getANWFormat(format)) { + case HAL_PIXEL_FORMAT_TI_NV12: + case HAL_PIXEL_FORMAT_TI_Y16: + case HAL_PIXEL_FORMAT_TI_UYVY: + // Assuming NV12 1D is RAW or Image frame + return CameraFrame::RAW_FRAME; + default: + break; + } + return CameraFrame::RAW_FRAME; +} + +static int getHeightFromFormat(const char* format, int stride, int size) { + CAMHAL_ASSERT((NULL != format) && (0 <= stride) && (0 <= size)); + switch (getANWFormat(format)) { + case HAL_PIXEL_FORMAT_TI_NV12: + return (size / (3 * stride)) * 2; + case HAL_PIXEL_FORMAT_TI_Y16: + case HAL_PIXEL_FORMAT_TI_UYVY: + return (size / stride) / 2; + default: + break; + } + return 0; +} + +/*--------------------BufferSourceAdapter Class STARTS here-----------------------------*/ + + +///Constant definitions +// TODO(XXX): Temporarily increase number of buffers we can allocate from ANW +// until faux-NPA mode is implemented +const int BufferSourceAdapter::NO_BUFFERS_IMAGE_CAPTURE_SYSTEM_HEAP = 15; + +/** + * Display Adapter class STARTS here.. + */ +BufferSourceAdapter::BufferSourceAdapter() : mBufferCount(0) +{ + LOG_FUNCTION_NAME; + + mPixelFormat = NULL; + mBuffers = NULL; + mFrameProvider = NULL; + mBufferSource = NULL; + + mFrameWidth = 0; + mFrameHeight = 0; + mPreviewWidth = 0; + mPreviewHeight = 0; + + LOG_FUNCTION_NAME_EXIT; +} + +BufferSourceAdapter::~BufferSourceAdapter() +{ + LOG_FUNCTION_NAME; + + freeBufferList(mBuffers); + + android::AutoMutex lock(mLock); + + destroy(); + + if (mFrameProvider) { + // Unregister with the frame provider + mFrameProvider->disableFrameNotification(CameraFrame::ALL_FRAMES); + delete mFrameProvider; + mFrameProvider = NULL; + } + + if (mQueueFrame.get()) { + mQueueFrame->requestExit(); + mQueueFrame.clear(); + } + + if (mReturnFrame.get()) { + mReturnFrame->requestExit(); + mReturnFrame.clear(); + } + + LOG_FUNCTION_NAME_EXIT; +} + +status_t BufferSourceAdapter::initialize() +{ + status_t ret = NO_ERROR; + + LOG_FUNCTION_NAME; + + mReturnFrame.clear(); + mReturnFrame = new ReturnFrame(this); + mReturnFrame->run(); + + mQueueFrame.clear(); + mQueueFrame = new QueueFrame(this); + mQueueFrame->run(); + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +int BufferSourceAdapter::setPreviewWindow(preview_stream_ops_t *source) +{ + LOG_FUNCTION_NAME; + + if (!source) { + CAMHAL_LOGEA("NULL window object passed to DisplayAdapter"); + LOG_FUNCTION_NAME_EXIT; + return BAD_VALUE; + } + + if (mBufferSource) { + char id1[OP_STR_SIZE], id2[OP_STR_SIZE]; + status_t ret; + + ret = extendedOps()->get_id(mBufferSource, id1, sizeof(id1)); + if (ret != 0) { + CAMHAL_LOGE("Surface::getId returned error %d", ret); + return ret; + } + + ret = extendedOps()->get_id(source, id2, sizeof(id2)); + if (ret != 0) { + CAMHAL_LOGE("Surface::getId returned error %d", ret); + return ret; + } + if ((0 >= strlen(id1)) || (0 >= strlen(id2))) { + CAMHAL_LOGE("Cannot set ST without name: id1:\"%s\" id2:\"%s\"", + id1, id2); + return NOT_ENOUGH_DATA; + } + if (0 == strcmp(id1, id2)) { + return ALREADY_EXISTS; + } + + // client has to unset mBufferSource before being able to set a new one + return BAD_VALUE; + } + + // Move to new source obj + mBufferSource = source; + + LOG_FUNCTION_NAME_EXIT; + + return NO_ERROR; +} + +bool BufferSourceAdapter::match(const char * str) { + char id1[OP_STR_SIZE]; + status_t ret; + + ret = extendedOps()->get_id(mBufferSource, id1, sizeof(id1)); + + if (ret != 0) { + CAMHAL_LOGE("Surface::getId returned error %d", ret); + } + + return strcmp(id1, str) == 0; +} + +int BufferSourceAdapter::setFrameProvider(FrameNotifier *frameProvider) +{ + LOG_FUNCTION_NAME; + + if ( !frameProvider ) { + CAMHAL_LOGEA("NULL passed for frame provider"); + LOG_FUNCTION_NAME_EXIT; + return BAD_VALUE; + } + + if ( NULL != mFrameProvider ) { + delete mFrameProvider; + } + + mFrameProvider = new FrameProvider(frameProvider, this, frameCallback); + + LOG_FUNCTION_NAME_EXIT; + + return NO_ERROR; +} + +int BufferSourceAdapter::setErrorHandler(ErrorNotifier *errorNotifier) +{ + status_t ret = NO_ERROR; + + LOG_FUNCTION_NAME; + + if ( NULL == errorNotifier ) { + CAMHAL_LOGEA("Invalid Error Notifier reference"); + return -EINVAL; + } + + mErrorNotifier = errorNotifier; + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +int BufferSourceAdapter::enableDisplay(int width, int height, + struct timeval *refTime) +{ + LOG_FUNCTION_NAME; + CameraFrame::FrameType frameType; + + if (mFrameProvider == NULL) { + // no-op frame provider not set yet + return NO_ERROR; + } + + if (mBufferSourceDirection == BUFFER_SOURCE_TAP_IN) { + // only supporting one type of input frame + frameType = CameraFrame::REPROCESS_INPUT_FRAME; + } else { + frameType = formatToOutputFrameType(mPixelFormat); + } + + mFrameProvider->enableFrameNotification(frameType); + LOG_FUNCTION_NAME_EXIT; + + return NO_ERROR; +} + +int BufferSourceAdapter::disableDisplay(bool cancel_buffer) +{ + LOG_FUNCTION_NAME; + + if (mFrameProvider) mFrameProvider->disableFrameNotification(CameraFrame::ALL_FRAMES); + + LOG_FUNCTION_NAME_EXIT; + + return NO_ERROR; +} + +status_t BufferSourceAdapter::pauseDisplay(bool pause) +{ + status_t ret = NO_ERROR; + + LOG_FUNCTION_NAME; + + // no-op for BufferSourceAdapter + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + + +void BufferSourceAdapter::destroy() +{ + LOG_FUNCTION_NAME; + + mBufferCount = 0; + + LOG_FUNCTION_NAME_EXIT; +} + +CameraBuffer* BufferSourceAdapter::allocateBufferList(int width, int dummyHeight, const char* format, + int &bytes, int numBufs) +{ + LOG_FUNCTION_NAME; + status_t err; + int i = -1; + const int lnumBufs = numBufs; + int undequeued = 0; + android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get(); + + mBuffers = new CameraBuffer [lnumBufs]; + memset (mBuffers, 0, sizeof(CameraBuffer) * lnumBufs); + + if ( NULL == mBufferSource ) { + return NULL; + } + + int pixFormat = getANWFormat(format); + int usage = getUsageFromANW(pixFormat); + mPixelFormat = CameraHal::getPixelFormatConstant(format); + + // Set gralloc usage bits for window. + err = mBufferSource->set_usage(mBufferSource, usage); + if (err != 0) { + CAMHAL_LOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err); + + if ( ENODEV == err ) { + CAMHAL_LOGEA("Preview surface abandoned!"); + mBufferSource = NULL; + } + + return NULL; + } + + CAMHAL_LOGDB("Number of buffers set to BufferSourceAdapter %d", numBufs); + // Set the number of buffers needed for this buffer source + err = mBufferSource->set_buffer_count(mBufferSource, numBufs); + if (err != 0) { + CAMHAL_LOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), -err); + + if ( ENODEV == err ) { + CAMHAL_LOGEA("Preview surface abandoned!"); + mBufferSource = NULL; + } + + return NULL; + } + + CAMHAL_LOGDB("Configuring %d buffers for ANativeWindow", numBufs); + mBufferCount = numBufs; + + // re-calculate height depending on stride and size + int height = getHeightFromFormat(format, width, bytes); + + // Set window geometry + err = mBufferSource->set_buffers_geometry(mBufferSource, + width, height, + pixFormat); + + if (err != 0) { + CAMHAL_LOGE("native_window_set_buffers_geometry failed: %s (%d)", strerror(-err), -err); + if ( ENODEV == err ) { + CAMHAL_LOGEA("Preview surface abandoned!"); + mBufferSource = NULL; + } + return NULL; + } + + if ( mBuffers == NULL ) { + CAMHAL_LOGEA("Couldn't create array for ANativeWindow buffers"); + LOG_FUNCTION_NAME_EXIT; + return NULL; + } + + mBufferSource->get_min_undequeued_buffer_count(mBufferSource, &undequeued); + + for (i = 0; i < mBufferCount; i++ ) { + buffer_handle_t *handle; + int stride; // dummy variable to get stride + // TODO(XXX): Do we need to keep stride information in camera hal? + + err = mBufferSource->dequeue_buffer(mBufferSource, &handle, &stride); + + if (err != 0) { + CAMHAL_LOGEB("dequeueBuffer failed: %s (%d)", strerror(-err), -err); + if ( ENODEV == err ) { + CAMHAL_LOGEA("Preview surface abandoned!"); + mBufferSource = NULL; + } + goto fail; + } + + CAMHAL_LOGDB("got handle %p", handle); + mBuffers[i].opaque = (void *)handle; + mBuffers[i].type = CAMERA_BUFFER_ANW; + mBuffers[i].format = mPixelFormat; + mFramesWithCameraAdapterMap.add(handle, i); + + bytes = CameraHal::calculateBufferSize(format, width, height); + } + + for( i = 0; i < mBufferCount-undequeued; i++ ) { + void *y_uv[2]; + android::Rect bounds(width, height); + + buffer_handle_t *handle = (buffer_handle_t *) mBuffers[i].opaque; + mBufferSource->lock_buffer(mBufferSource, handle); + mapper.lock(*handle, CAMHAL_GRALLOC_USAGE, bounds, y_uv); + mBuffers[i].mapped = y_uv[0]; + } + + // return the rest of the buffers back to ANativeWindow + for(i = (mBufferCount-undequeued); i >= 0 && i < mBufferCount; i++) { + buffer_handle_t *handle = (buffer_handle_t *) mBuffers[i].opaque; + void *y_uv[2]; + android::Rect bounds(width, height); + + mapper.lock(*handle, CAMHAL_GRALLOC_USAGE, bounds, y_uv); + mBuffers[i].mapped = y_uv[0]; + mapper.unlock(*handle); + + err = mBufferSource->cancel_buffer(mBufferSource, handle); + if (err != 0) { + CAMHAL_LOGEB("cancel_buffer failed: %s (%d)", strerror(-err), -err); + if ( ENODEV == err ) { + CAMHAL_LOGEA("Preview surface abandoned!"); + mBufferSource = NULL; + } + goto fail; + } + mFramesWithCameraAdapterMap.removeItem((buffer_handle_t *) mBuffers[i].opaque); + } + + mFrameWidth = width; + mFrameHeight = height; + mBufferSourceDirection = BUFFER_SOURCE_TAP_OUT; + + return mBuffers; + + fail: + // need to cancel buffers if any were dequeued + for (int start = 0; start < i && i > 0; start++) { + int err = mBufferSource->cancel_buffer(mBufferSource, + (buffer_handle_t *) mBuffers[start].opaque); + if (err != 0) { + CAMHAL_LOGEB("cancelBuffer failed w/ error 0x%08x", err); + break; + } + mFramesWithCameraAdapterMap.removeItem((buffer_handle_t *) mBuffers[start].opaque); + } + + freeBufferList(mBuffers); + + CAMHAL_LOGEA("Error occurred, performing cleanup"); + + if (NULL != mErrorNotifier.get()) { + mErrorNotifier->errorNotify(-ENOMEM); + } + + LOG_FUNCTION_NAME_EXIT; + return NULL; + +} + +CameraBuffer *BufferSourceAdapter::getBuffers(bool reset) { + int undequeued = 0; + status_t err; + android::Mutex::Autolock lock(mLock); + + if (!mBufferSource || !mBuffers) { + CAMHAL_LOGE("Adapter is not set up properly: " + "mBufferSource:%p mBuffers:%p", + mBufferSource, mBuffers); + goto fail; + } + + // CameraHal is indicating to us that the state of the mBuffer + // might have changed. We might need to check the state of the + // buffer list and pass a new one depending on the state of our + // surface + if (reset) { + const int lnumBufs = mBufferCount; + android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get(); + android::Rect bounds(mFrameWidth, mFrameHeight); + void *y_uv[2]; + CameraBuffer * newBuffers = NULL; + unsigned int index = 0; + android::KeyedVector<void*, int> missingIndices; + + newBuffers = new CameraBuffer [lnumBufs]; + memset (newBuffers, 0, sizeof(CameraBuffer) * lnumBufs); + + // Use this vector to figure out missing indices + for (int i = 0; i < mBufferCount; i++) { + missingIndices.add(mBuffers[i].opaque, i); + } + + // assign buffers that we have already dequeued + for (index = 0; index < mFramesWithCameraAdapterMap.size(); index++) { + int value = mFramesWithCameraAdapterMap.valueAt(index); + newBuffers[index].opaque = mBuffers[value].opaque; + newBuffers[index].type = mBuffers[value].type; + newBuffers[index].format = mBuffers[value].format; + newBuffers[index].mapped = mBuffers[value].mapped; + mFramesWithCameraAdapterMap.replaceValueAt(index, index); + missingIndices.removeItem(newBuffers[index].opaque); + } + + mBufferSource->get_min_undequeued_buffer_count(mBufferSource, &undequeued); + + // dequeue the rest of the buffers + for (index; index < (unsigned int)(mBufferCount-undequeued); index++) { + buffer_handle_t *handle; + int stride; // dummy variable to get stride + + err = mBufferSource->dequeue_buffer(mBufferSource, &handle, &stride); + if (err != 0) { + CAMHAL_LOGEB("dequeueBuffer failed: %s (%d)", strerror(-err), -err); + if ( ENODEV == err ) { + CAMHAL_LOGEA("Preview surface abandoned!"); + mBufferSource = NULL; + } + goto fail; + } + newBuffers[index].opaque = (void *)handle; + newBuffers[index].type = CAMERA_BUFFER_ANW; + newBuffers[index].format = mPixelFormat; + mFramesWithCameraAdapterMap.add(handle, index); + + mBufferSource->lock_buffer(mBufferSource, handle); + mapper.lock(*handle, CAMHAL_GRALLOC_USAGE, bounds, y_uv); + newBuffers[index].mapped = y_uv[0]; + CAMHAL_LOGDB("got handle %p", handle); + + missingIndices.removeItem(newBuffers[index].opaque); + } + + // now we need to figure out which buffers aren't dequeued + // which are in mBuffers but not newBuffers yet + if ((mBufferCount - index) != missingIndices.size()) { + CAMHAL_LOGD("Hrmm somethings gone awry. We are missing a different number" + " of buffers than we can fill"); + } + for (unsigned int i = 0; i < missingIndices.size(); i++) { + int j = missingIndices.valueAt(i); + + CAMHAL_LOGD("Filling at %d", j); + newBuffers[index].opaque = mBuffers[j].opaque; + newBuffers[index].type = mBuffers[j].type; + newBuffers[index].format = mBuffers[j].format; + newBuffers[index].mapped = mBuffers[j].mapped; + } + + delete [] mBuffers; + mBuffers = newBuffers; + } + + return mBuffers; + + fail: + return NULL; +} + +unsigned int BufferSourceAdapter::getSize() { + android::Mutex::Autolock lock(mLock); + return CameraHal::calculateBufferSize(mPixelFormat, mFrameWidth, mFrameHeight); +} + +int BufferSourceAdapter::getBufferCount() { + int count = -1; + + android::Mutex::Autolock lock(mLock); + if (mBufferSource) extendedOps()->get_buffer_count(mBufferSource, &count); + return count; +} + +CameraBuffer* BufferSourceAdapter::getBufferList(int *num) { + LOG_FUNCTION_NAME; + status_t err; + const int lnumBufs = 1; + int formatSource; + android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get(); + buffer_handle_t *handle; + + // TODO(XXX): Only supporting one input buffer at a time right now + *num = 1; + mBufferCount = *num; + mBuffers = new CameraBuffer [lnumBufs]; + memset (mBuffers, 0, sizeof(CameraBuffer) * lnumBufs); + + if ( NULL == mBufferSource ) { + return NULL; + } + + err = extendedOps()->update_and_get_buffer(mBufferSource, + &handle, + &mBuffers[0].stride, + &mBuffers[0].privateData); + if (err != 0) { + CAMHAL_LOGEB("update and get buffer failed: %s (%d)", strerror(-err), -err); + if ( ENODEV == err ) { + CAMHAL_LOGEA("Preview surface abandoned!"); + mBufferSource = NULL; + } + goto fail; + } + + CAMHAL_LOGD("got handle %p", handle); + mBuffers[0].opaque = (void *)handle; + mBuffers[0].type = CAMERA_BUFFER_ANW; + mFramesWithCameraAdapterMap.add(handle, 0); + + err = extendedOps()->get_buffer_dimension(mBufferSource, &mBuffers[0].width, &mBuffers[0].height); + err = extendedOps()->get_buffer_format(mBufferSource, &formatSource); + + int t, l, r, b, w, h; + err = extendedOps()->get_crop(mBufferSource, &l, &t, &r, &b); + err = extendedOps()->get_current_size(mBufferSource, &w, &h); + + // lock buffer + { + void *y_uv[2]; + android::Rect bounds(mBuffers[0].width, mBuffers[0].height); + mapper.lock(*handle, CAMHAL_GRALLOC_USAGE, bounds, y_uv); + mBuffers[0].mapped = y_uv[0]; + } + + mFrameWidth = mBuffers[0].width; + mFrameHeight = mBuffers[0].height; + mPixelFormat = getFormatFromANW(formatSource); + + mBuffers[0].format = mPixelFormat; + mBuffers[0].actual_size = CameraHal::calculateBufferSize(mPixelFormat, w, h); + mBuffers[0].offset = t * w + l * CameraHal::getBPP(mPixelFormat); + mBufferSourceDirection = BUFFER_SOURCE_TAP_IN; + + return mBuffers; + + fail: + // need to cancel buffers if any were dequeued + freeBufferList(mBuffers); + + if (NULL != mErrorNotifier.get()) { + mErrorNotifier->errorNotify(-ENOMEM); + } + + LOG_FUNCTION_NAME_EXIT; + return NULL; +} + +uint32_t * BufferSourceAdapter::getOffsets() +{ + LOG_FUNCTION_NAME; + + LOG_FUNCTION_NAME_EXIT; + + return NULL; +} + +int BufferSourceAdapter::minUndequeueableBuffers(int& undequeueable) { + LOG_FUNCTION_NAME; + int ret = NO_ERROR; + + if(!mBufferSource) + { + ret = INVALID_OPERATION; + goto end; + } + + ret = mBufferSource->get_min_undequeued_buffer_count(mBufferSource, &undequeueable); + if ( NO_ERROR != ret ) { + CAMHAL_LOGEB("get_min_undequeued_buffer_count failed: %s (%d)", strerror(-ret), -ret); + if ( ENODEV == ret ) { + CAMHAL_LOGEA("Preview surface abandoned!"); + mBufferSource = NULL; + } + return -ret; + } + + end: + return ret; + LOG_FUNCTION_NAME_EXIT; + +} + +int BufferSourceAdapter::maxQueueableBuffers(unsigned int& queueable) +{ + LOG_FUNCTION_NAME; + int ret = NO_ERROR; + int undequeued = 0; + + if(mBufferCount == 0) { + ret = INVALID_OPERATION; + goto end; + } + + ret = minUndequeueableBuffers(undequeued); + if (ret != NO_ERROR) { + goto end; + } + + queueable = mBufferCount - undequeued; + + end: + return ret; + LOG_FUNCTION_NAME_EXIT; +} + +int BufferSourceAdapter::getFd() +{ + LOG_FUNCTION_NAME; + + LOG_FUNCTION_NAME_EXIT; + + return -1; + +} + +status_t BufferSourceAdapter::returnBuffersToWindow() +{ + status_t ret = NO_ERROR; + android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get(); + + //Give the buffers back to display here - sort of free it + if (mBufferSource) { + for(unsigned int i = 0; i < mFramesWithCameraAdapterMap.size(); i++) { + int value = mFramesWithCameraAdapterMap.valueAt(i); + buffer_handle_t *handle = (buffer_handle_t *) mBuffers[value].opaque; + + // if buffer index is out of bounds skip + if ((value < 0) || (value >= mBufferCount)) { + CAMHAL_LOGEA("Potential out bounds access to handle...skipping"); + continue; + } + + // unlock buffer before giving it up + mapper.unlock(*handle); + + ret = mBufferSource->cancel_buffer(mBufferSource, handle); + if ( ENODEV == ret ) { + CAMHAL_LOGEA("Preview surface abandoned!"); + mBufferSource = NULL; + return -ret; + } else if ( NO_ERROR != ret ) { + CAMHAL_LOGEB("cancel_buffer() failed: %s (%d)", + strerror(-ret), + -ret); + return -ret; + } + } + } else { + CAMHAL_LOGE("mBufferSource is NULL"); + } + + ///Clear the frames with camera adapter map + mFramesWithCameraAdapterMap.clear(); + + return ret; + +} + +int BufferSourceAdapter::freeBufferList(CameraBuffer * buflist) +{ + LOG_FUNCTION_NAME; + + status_t ret = NO_ERROR; + + if ( mBuffers != buflist ) { + return BAD_VALUE; + } + + android::AutoMutex lock(mLock); + + if (mBufferSourceDirection == BUFFER_SOURCE_TAP_OUT) returnBuffersToWindow(); + + if( mBuffers != NULL) + { + delete [] mBuffers; + mBuffers = NULL; + } + + return NO_ERROR; +} + + +bool BufferSourceAdapter::supportsExternalBuffering() +{ + return false; +} + +void BufferSourceAdapter::addFrame(CameraFrame* frame) +{ + if (mQueueFrame.get()) { + mQueueFrame->addFrame(frame); + } +} + +void BufferSourceAdapter::handleFrameCallback(CameraFrame* frame) +{ + status_t ret = NO_ERROR; + buffer_handle_t *handle = NULL; + int i; + uint32_t x, y; + android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get(); + + android::AutoMutex lock(mLock); + + if (!mBuffers || !frame->mBuffer) { + CAMHAL_LOGEA("Adapter sent BufferSourceAdapter a NULL frame?"); + return; + } + + for ( i = 0; i < mBufferCount; i++ ) { + if (frame->mBuffer == &mBuffers[i]) { + break; + } + } + + if (i >= mBufferCount) { + CAMHAL_LOGD("Can't find frame in buffer list"); + if (frame->mFrameType != CameraFrame::REPROCESS_INPUT_FRAME) { + mFrameProvider->returnFrame(frame->mBuffer, + static_cast<CameraFrame::FrameType>(frame->mFrameType)); + } + return; + } + + handle = (buffer_handle_t *) mBuffers[i].opaque; + + // Handle input buffers + // TODO(XXX): Move handling of input buffers out of here if + // it becomes more complex + if (frame->mFrameType == CameraFrame::REPROCESS_INPUT_FRAME) { + CAMHAL_LOGD("Unlock %p (buffer #%d)", handle, i); + mapper.unlock(*handle); + extendedOps()->release_buffer(mBufferSource, mBuffers[i].privateData); + return; + } + + CameraHal::getXYFromOffset(&x, &y, frame->mOffset, frame->mAlignment, mPixelFormat); + CAMHAL_LOGVB("offset = %u left = %d top = %d right = %d bottom = %d", + frame->mOffset, x, y, x + frame->mWidth, y + frame->mHeight); + ret = mBufferSource->set_crop(mBufferSource, x, y, x + frame->mWidth, y + frame->mHeight); + if (NO_ERROR != ret) { + CAMHAL_LOGE("mBufferSource->set_crop returned error %d", ret); + goto fail; + } + + if ( NULL != frame->mMetaData.get() ) { + camera_memory_t *extMeta = frame->mMetaData->getExtendedMetadata(); + if ( NULL != extMeta ) { + camera_metadata_t *metaData = static_cast<camera_metadata_t *> (extMeta->data); + metaData->timestamp = frame->mTimestamp; + ret = extendedOps()->set_metadata(mBufferSource, extMeta); + if (ret != 0) { + CAMHAL_LOGE("Surface::set_metadata returned error %d", ret); + goto fail; + } + } + } + + // unlock buffer before enqueueing + mapper.unlock(*handle); + + ret = mBufferSource->enqueue_buffer(mBufferSource, handle); + if (ret != 0) { + CAMHAL_LOGE("Surface::queueBuffer returned error %d", ret); + goto fail; + } + + mFramesWithCameraAdapterMap.removeItem((buffer_handle_t *) frame->mBuffer->opaque); + + return; + +fail: + mFramesWithCameraAdapterMap.clear(); + mBufferSource = NULL; + mReturnFrame->requestExit(); + mQueueFrame->requestExit(); +} + + +bool BufferSourceAdapter::handleFrameReturn() +{ + status_t err; + buffer_handle_t *buf; + int i = 0; + int stride; // dummy variable to get stride + CameraFrame::FrameType type; + android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get(); + void *y_uv[2]; + android::Rect bounds(mFrameWidth, mFrameHeight); + + android::AutoMutex lock(mLock); + + if ( (NULL == mBufferSource) || (NULL == mBuffers) ) { + return false; + } + + err = mBufferSource->dequeue_buffer(mBufferSource, &buf, &stride); + if (err != 0) { + CAMHAL_LOGEB("dequeueBuffer failed: %s (%d)", strerror(-err), -err); + + if ( ENODEV == err ) { + CAMHAL_LOGEA("Preview surface abandoned!"); + mBufferSource = NULL; + } + + return false; + } + + err = mBufferSource->lock_buffer(mBufferSource, buf); + if (err != 0) { + CAMHAL_LOGEB("lockbuffer failed: %s (%d)", strerror(-err), -err); + + if ( ENODEV == err ) { + CAMHAL_LOGEA("Preview surface abandoned!"); + mBufferSource = NULL; + } + + return false; + } + + mapper.lock(*buf, CAMHAL_GRALLOC_USAGE, bounds, y_uv); + + for(i = 0; i < mBufferCount; i++) { + if (mBuffers[i].opaque == buf) + break; + } + + if (i >= mBufferCount) { + CAMHAL_LOGEB("Failed to find handle %p", buf); + } + + mFramesWithCameraAdapterMap.add((buffer_handle_t *) mBuffers[i].opaque, i); + + CAMHAL_LOGVB("handleFrameReturn: found graphic buffer %d of %d", i, mBufferCount - 1); + + mFrameProvider->returnFrame(&mBuffers[i], formatToOutputFrameType(mPixelFormat)); + return true; +} + +void BufferSourceAdapter::frameCallback(CameraFrame* caFrame) +{ + if ((NULL != caFrame) && (NULL != caFrame->mCookie)) { + BufferSourceAdapter *da = (BufferSourceAdapter*) caFrame->mCookie; + da->addFrame(caFrame); + } else { + CAMHAL_LOGEB("Invalid Cookie in Camera Frame = %p, Cookie = %p", + caFrame, caFrame ? caFrame->mCookie : NULL); + } +} + +/*--------------------BufferSourceAdapter Class ENDS here-----------------------------*/ + +} // namespace Camera +} // namespace Ti + +#endif |