aboutsummaryrefslogtreecommitdiff
path: root/camera/QCamera2/HAL/QCameraMem.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xcamera/QCamera2/HAL/QCameraMem.cpp2448
1 files changed, 2448 insertions, 0 deletions
diff --git a/camera/QCamera2/HAL/QCameraMem.cpp b/camera/QCamera2/HAL/QCameraMem.cpp
new file mode 100755
index 0000000..00f1548
--- /dev/null
+++ b/camera/QCamera2/HAL/QCameraMem.cpp
@@ -0,0 +1,2448 @@
+/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#define LOG_TAG "QCameraHWI_Mem"
+
+// System dependencies
+#include <fcntl.h>
+#include <stdio.h>
+#include <utils/Errors.h>
+#define MMAN_H <SYSTEM_HEADER_PREFIX/mman.h>
+#include MMAN_H
+#include "gralloc.h"
+#include "gralloc_priv.h"
+
+// Camera dependencies
+#include "QCamera2HWI.h"
+#include "QCameraMem.h"
+#include "QCameraParameters.h"
+#include "QCameraTrace.h"
+
+// Media dependencies
+#include "OMX_QCOMExtns.h"
+#ifdef USE_MEDIA_EXTENSIONS
+#include <media/hardware/HardwareAPI.h>
+typedef struct VideoNativeHandleMetadata media_metadata_buffer;
+#else
+#include "QComOMXMetadata.h"
+typedef struct encoder_media_buffer_type media_metadata_buffer;
+#endif
+
+extern "C" {
+#include "mm_camera_dbg.h"
+#include "mm_camera_interface.h"
+}
+
+using namespace android;
+
+namespace qcamera {
+
+// QCaemra2Memory base class
+
+/*===========================================================================
+ * FUNCTION : QCameraMemory
+ *
+ * DESCRIPTION: default constructor of QCameraMemory
+ *
+ * PARAMETERS :
+ * @cached : flag indicates if using cached memory
+ *
+ * RETURN : None
+ *==========================================================================*/
+QCameraMemory::QCameraMemory(bool cached,
+ QCameraMemoryPool *pool,
+ cam_stream_type_t streamType, QCameraMemType bufType)
+ :m_bCached(cached),
+ mMemoryPool(pool),
+ mStreamType(streamType),
+ mBufType(bufType)
+{
+ mBufferCount = 0;
+ reset();
+}
+
+/*===========================================================================
+ * FUNCTION : ~QCameraMemory
+ *
+ * DESCRIPTION: deconstructor of QCameraMemory
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : None
+ *==========================================================================*/
+QCameraMemory::~QCameraMemory()
+{
+}
+
+/*===========================================================================
+ * FUNCTION : cacheOpsInternal
+ *
+ * DESCRIPTION: ion related memory cache operations
+ *
+ * PARAMETERS :
+ * @index : index of the buffer
+ * @cmd : cache ops command
+ * @vaddr : ptr to the virtual address
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraMemory::cacheOpsInternal(uint32_t index, unsigned int cmd, void *vaddr)
+{
+ if (!m_bCached) {
+ // Memory is not cached, no need for cache ops
+ LOGD("No cache ops here for uncached memory");
+ return OK;
+ }
+
+ struct ion_flush_data cache_inv_data;
+ struct ion_custom_data custom_data;
+ int ret = OK;
+
+ if (index >= mBufferCount) {
+ LOGE("index %d out of bound [0, %d)", index, mBufferCount);
+ return BAD_INDEX;
+ }
+
+ memset(&cache_inv_data, 0, sizeof(cache_inv_data));
+ memset(&custom_data, 0, sizeof(custom_data));
+ cache_inv_data.vaddr = vaddr;
+ cache_inv_data.fd = mMemInfo[index].fd;
+ cache_inv_data.handle = mMemInfo[index].handle;
+ cache_inv_data.length =
+ ( /* FIXME: Should remove this after ION interface changes */ unsigned int)
+ mMemInfo[index].size;
+ custom_data.cmd = cmd;
+ custom_data.arg = (unsigned long)&cache_inv_data;
+
+ LOGH("addr = %p, fd = %d, handle = %lx length = %d, ION Fd = %d",
+ cache_inv_data.vaddr, cache_inv_data.fd,
+ (unsigned long)cache_inv_data.handle, cache_inv_data.length,
+ mMemInfo[index].main_ion_fd);
+ ret = ioctl(mMemInfo[index].main_ion_fd, ION_IOC_CUSTOM, &custom_data);
+ if (ret < 0) {
+ LOGE("Cache Invalidate failed: %s\n", strerror(errno));
+ }
+
+ return ret;
+}
+
+/*===========================================================================
+ * FUNCTION : getFd
+ *
+ * DESCRIPTION: return file descriptor of the indexed buffer
+ *
+ * PARAMETERS :
+ * @index : index of the buffer
+ *
+ * RETURN : file descriptor
+ *==========================================================================*/
+int QCameraMemory::getFd(uint32_t index) const
+{
+ if (index >= mBufferCount)
+ return BAD_INDEX;
+
+ return mMemInfo[index].fd;
+}
+
+/*===========================================================================
+ * FUNCTION : getSize
+ *
+ * DESCRIPTION: return buffer size of the indexed buffer
+ *
+ * PARAMETERS :
+ * @index : index of the buffer
+ *
+ * RETURN : buffer size
+ *==========================================================================*/
+ssize_t QCameraMemory::getSize(uint32_t index) const
+{
+ if (index >= mBufferCount)
+ return BAD_INDEX;
+
+ return (ssize_t)mMemInfo[index].size;
+}
+
+/*===========================================================================
+ * FUNCTION : getCnt
+ *
+ * DESCRIPTION: query number of buffers allocated
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : number of buffers allocated
+ *==========================================================================*/
+uint8_t QCameraMemory::getCnt() const
+{
+ return mBufferCount;
+}
+
+/*===========================================================================
+ * FUNCTION : reset
+ *
+ * DESCRIPTION: reset member variables
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+void QCameraMemory::reset()
+{
+ size_t i, count;
+
+ memset(mMemInfo, 0, sizeof(mMemInfo));
+
+ count = sizeof(mMemInfo) / sizeof(mMemInfo[0]);
+ for (i = 0; i < count; i++) {
+ mMemInfo[i].fd = -1;
+ mMemInfo[i].main_ion_fd = -1;
+ }
+
+ return;
+}
+
+/*===========================================================================
+ * FUNCTION : getMappable
+ *
+ * DESCRIPTION: query number of buffers available to map
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : number of buffers available to map
+ *==========================================================================*/
+uint8_t QCameraMemory::getMappable() const
+{
+ return mBufferCount;
+}
+
+/*===========================================================================
+ * FUNCTION : checkIfAllBuffersMapped
+ *
+ * DESCRIPTION: query if all buffers are mapped
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : 1 as buffer count is always equal to mappable count
+ *==========================================================================*/
+uint8_t QCameraMemory::checkIfAllBuffersMapped() const
+{
+ return 1;
+}
+
+
+/*===========================================================================
+ * FUNCTION : getBufDef
+ *
+ * DESCRIPTION: query detailed buffer information
+ *
+ * PARAMETERS :
+ * @offset : [input] frame buffer offset
+ * @bufDef : [output] reference to struct to store buffer definition
+ * @index : [input] index of the buffer
+ *
+ * RETURN : none
+ *==========================================================================*/
+void QCameraMemory::getBufDef(const cam_frame_len_offset_t &offset,
+ mm_camera_buf_def_t &bufDef, uint32_t index) const
+{
+ if (!mBufferCount) {
+ LOGE("Memory not allocated");
+ return;
+ }
+ bufDef.fd = mMemInfo[index].fd;
+ bufDef.frame_len = mMemInfo[index].size;
+ bufDef.buf_type = CAM_STREAM_BUF_TYPE_MPLANE;
+ bufDef.mem_info = (void *)this;
+ bufDef.planes_buf.num_planes = (int8_t)offset.num_planes;
+ bufDef.buffer = getPtr(index);
+ bufDef.buf_idx = index;
+
+ /* Plane 0 needs to be set separately. Set other planes in a loop */
+ bufDef.planes_buf.planes[0].length = offset.mp[0].len;
+ bufDef.planes_buf.planes[0].m.userptr = (long unsigned int)mMemInfo[index].fd;
+ bufDef.planes_buf.planes[0].data_offset = offset.mp[0].offset;
+ bufDef.planes_buf.planes[0].reserved[0] = 0;
+ for (int i = 1; i < bufDef.planes_buf.num_planes; i++) {
+ bufDef.planes_buf.planes[i].length = offset.mp[i].len;
+ bufDef.planes_buf.planes[i].m.userptr = (long unsigned int)mMemInfo[i].fd;
+ bufDef.planes_buf.planes[i].data_offset = offset.mp[i].offset;
+ bufDef.planes_buf.planes[i].reserved[0] =
+ bufDef.planes_buf.planes[i-1].reserved[0] +
+ bufDef.planes_buf.planes[i-1].length;
+ }
+}
+
+/*===========================================================================
+ * FUNCTION : getUserBufDef
+ *
+ * DESCRIPTION: Fill Buffer structure with user buffer information
+ This also fills individual stream buffers inside batch baffer strcuture
+ *
+ * PARAMETERS :
+ * @buf_info : user buffer information
+ * @bufDef : Buffer strcuture to fill user buf info
+ * @index : index of the buffer
+ * @plane_offset : plane buffer information
+ * @planeBufDef : [input] frame buffer offset
+ * @bufs : Stream Buffer object
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraMemory::getUserBufDef(const cam_stream_user_buf_info_t &buf_info,
+ mm_camera_buf_def_t &bufDef,
+ uint32_t index,
+ const cam_frame_len_offset_t &plane_offset,
+ mm_camera_buf_def_t *planeBufDef,
+ QCameraMemory *bufs) const
+{
+ struct msm_camera_user_buf_cont_t *cont_buf = NULL;
+ uint32_t plane_idx = (index * buf_info.frame_buf_cnt);
+
+ if (!mBufferCount) {
+ LOGE("Memory not allocated");
+ return INVALID_OPERATION;
+ }
+
+ for (int count = 0; count < mBufferCount; count++) {
+ bufDef.fd = mMemInfo[count].fd;
+ bufDef.buf_type = CAM_STREAM_BUF_TYPE_USERPTR;
+ bufDef.frame_len = buf_info.size;
+ bufDef.mem_info = (void *)this;
+ bufDef.buffer = (void *)((uint8_t *)getPtr(count)
+ + (index * buf_info.size));
+ bufDef.buf_idx = index;
+ bufDef.user_buf.num_buffers = (int8_t)buf_info.frame_buf_cnt;
+ bufDef.user_buf.bufs_used = (int8_t)buf_info.frame_buf_cnt;
+
+ //Individual plane buffer structure to be filled
+ cont_buf = (struct msm_camera_user_buf_cont_t *)bufDef.buffer;
+ cont_buf->buf_cnt = bufDef.user_buf.num_buffers;
+
+ for (int i = 0; i < bufDef.user_buf.num_buffers; i++) {
+ bufs->getBufDef(plane_offset, planeBufDef[plane_idx], plane_idx);
+ bufDef.user_buf.buf_idx[i] = -1;
+ cont_buf->buf_idx[i] = planeBufDef[plane_idx].buf_idx;
+ plane_idx++;
+ }
+ bufDef.user_buf.plane_buf = planeBufDef;
+
+ LOGD("num_buf = %d index = %d plane_idx = %d",
+ bufDef.user_buf.num_buffers, index, plane_idx);
+ }
+ return NO_ERROR;
+}
+
+
+/*===========================================================================
+ * FUNCTION : alloc
+ *
+ * DESCRIPTION: allocate requested number of buffers of certain size
+ *
+ * PARAMETERS :
+ * @count : number of buffers to be allocated
+ * @size : lenght of the buffer to be allocated
+ * @heap_id : heap id to indicate where the buffers will be allocated from
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraMemory::alloc(int count, size_t size, unsigned int heap_id,
+ uint32_t secure_mode)
+{
+ int rc = OK;
+
+ int new_bufCnt = mBufferCount + count;
+ ATRACE_BEGIN_SNPRINTF("%s %zu %d", "Memsize", size, count);
+
+ if (new_bufCnt > MM_CAMERA_MAX_NUM_FRAMES) {
+ LOGE("Buffer count %d out of bound. Max is %d",
+ new_bufCnt, MM_CAMERA_MAX_NUM_FRAMES);
+ ATRACE_END();
+ return BAD_INDEX;
+ }
+
+ for (int i = mBufferCount; i < new_bufCnt; i ++) {
+ if ( NULL == mMemoryPool ) {
+ LOGH("No memory pool available, allocating now");
+ rc = allocOneBuffer(mMemInfo[i], heap_id, size, m_bCached,
+ secure_mode);
+ if (rc < 0) {
+ LOGE("AllocateIonMemory failed");
+ for (int j = i-1; j >= 0; j--)
+ deallocOneBuffer(mMemInfo[j]);
+ break;
+ }
+ } else {
+ rc = mMemoryPool->allocateBuffer(mMemInfo[i],
+ heap_id,
+ size,
+ m_bCached,
+ mStreamType,
+ secure_mode);
+ if (rc < 0) {
+ LOGE("Memory pool allocation failed");
+ for (int j = i-1; j >= 0; j--)
+ mMemoryPool->releaseBuffer(mMemInfo[j],
+ mStreamType);
+ break;
+ }
+ }
+
+ }
+ ATRACE_END();
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : dealloc
+ *
+ * DESCRIPTION: deallocate buffers
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+void QCameraMemory::dealloc()
+{
+ for (int i = 0; i < mBufferCount; i++) {
+ if ( NULL == mMemoryPool ) {
+ deallocOneBuffer(mMemInfo[i]);
+ } else {
+ mMemoryPool->releaseBuffer(mMemInfo[i], mStreamType);
+ }
+ }
+}
+
+/*===========================================================================
+ * FUNCTION : allocOneBuffer
+ *
+ * DESCRIPTION: impl of allocating one buffers of certain size
+ *
+ * PARAMETERS :
+ * @memInfo : [output] reference to struct to store additional memory allocation info
+ * @heap : [input] heap id to indicate where the buffers will be allocated from
+ * @size : [input] lenght of the buffer to be allocated
+ * @cached : [input] flag whether buffer needs to be cached
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraMemory::allocOneBuffer(QCameraMemInfo &memInfo,
+ unsigned int heap_id, size_t size, bool cached, uint32_t secure_mode)
+{
+ int rc = OK;
+ struct ion_handle_data handle_data;
+ struct ion_allocation_data alloc;
+ struct ion_fd_data ion_info_fd;
+ int main_ion_fd = -1;
+
+ main_ion_fd = open("/dev/ion", O_RDONLY);
+ if (main_ion_fd < 0) {
+ LOGE("Ion dev open failed: %s\n", strerror(errno));
+ goto ION_OPEN_FAILED;
+ }
+
+ memset(&alloc, 0, sizeof(alloc));
+ alloc.len = size;
+ /* to make it page size aligned */
+ alloc.len = (alloc.len + 4095U) & (~4095U);
+ alloc.align = 4096;
+ if (cached) {
+ alloc.flags = ION_FLAG_CACHED;
+ }
+ alloc.heap_id_mask = heap_id;
+ if (secure_mode == SECURE) {
+ LOGD("Allocate secure buffer\n");
+ alloc.flags = ION_SECURE;
+ alloc.heap_id_mask = ION_HEAP(ION_CP_MM_HEAP_ID);
+ alloc.align = 1048576; // 1 MiB alignment to be able to protect later
+ alloc.len = (alloc.len + 1048575U) & (~1048575U);
+ }
+
+ rc = ioctl(main_ion_fd, ION_IOC_ALLOC, &alloc);
+ if (rc < 0) {
+ LOGE("ION allocation failed: %s\n", strerror(errno));
+ goto ION_ALLOC_FAILED;
+ }
+
+ memset(&ion_info_fd, 0, sizeof(ion_info_fd));
+ ion_info_fd.handle = alloc.handle;
+ rc = ioctl(main_ion_fd, ION_IOC_SHARE, &ion_info_fd);
+ if (rc < 0) {
+ LOGE("ION map failed %s\n", strerror(errno));
+ goto ION_MAP_FAILED;
+ }
+
+ memInfo.main_ion_fd = main_ion_fd;
+ memInfo.fd = ion_info_fd.fd;
+ memInfo.handle = ion_info_fd.handle;
+ memInfo.size = alloc.len;
+ memInfo.cached = cached;
+ memInfo.heap_id = heap_id;
+
+ LOGD("ION buffer %lx with size %d allocated",
+ (unsigned long)memInfo.handle, alloc.len);
+ return OK;
+
+ION_MAP_FAILED:
+ memset(&handle_data, 0, sizeof(handle_data));
+ handle_data.handle = ion_info_fd.handle;
+ ioctl(main_ion_fd, ION_IOC_FREE, &handle_data);
+ION_ALLOC_FAILED:
+ close(main_ion_fd);
+ION_OPEN_FAILED:
+ return NO_MEMORY;
+}
+
+/*===========================================================================
+ * FUNCTION : deallocOneBuffer
+ *
+ * DESCRIPTION: impl of deallocating one buffers
+ *
+ * PARAMETERS :
+ * @memInfo : reference to struct that stores additional memory allocation info
+ *
+ * RETURN : none
+ *==========================================================================*/
+void QCameraMemory::deallocOneBuffer(QCameraMemInfo &memInfo)
+{
+ struct ion_handle_data handle_data;
+
+ if (memInfo.fd >= 0) {
+ close(memInfo.fd);
+ memInfo.fd = -1;
+ }
+
+ if (memInfo.main_ion_fd >= 0) {
+ memset(&handle_data, 0, sizeof(handle_data));
+ handle_data.handle = memInfo.handle;
+ ioctl(memInfo.main_ion_fd, ION_IOC_FREE, &handle_data);
+ close(memInfo.main_ion_fd);
+ memInfo.main_ion_fd = -1;
+ }
+ memInfo.handle = 0;
+ memInfo.size = 0;
+}
+
+/*===========================================================================
+ * FUNCTION : QCameraMemoryPool
+ *
+ * DESCRIPTION: default constructor of QCameraMemoryPool
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : None
+ *==========================================================================*/
+QCameraMemoryPool::QCameraMemoryPool()
+{
+ pthread_mutex_init(&mLock, NULL);
+}
+
+
+/*===========================================================================
+ * FUNCTION : ~QCameraMemoryPool
+ *
+ * DESCRIPTION: deconstructor of QCameraMemoryPool
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : None
+ *==========================================================================*/
+QCameraMemoryPool::~QCameraMemoryPool()
+{
+ clear();
+ pthread_mutex_destroy(&mLock);
+}
+
+/*===========================================================================
+ * FUNCTION : releaseBuffer
+ *
+ * DESCRIPTION: release one cached buffers
+ *
+ * PARAMETERS :
+ * @memInfo : reference to struct that stores additional memory allocation info
+ * @streamType: Type of stream the buffers belongs to
+ *
+ * RETURN : none
+ *==========================================================================*/
+void QCameraMemoryPool::releaseBuffer(
+ struct QCameraMemory::QCameraMemInfo &memInfo,
+ cam_stream_type_t streamType)
+{
+ pthread_mutex_lock(&mLock);
+
+ mPools[streamType].push_back(memInfo);
+
+ pthread_mutex_unlock(&mLock);
+}
+
+/*===========================================================================
+ * FUNCTION : clear
+ *
+ * DESCRIPTION: clears all cached buffers
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+void QCameraMemoryPool::clear()
+{
+ pthread_mutex_lock(&mLock);
+
+ for (int i = CAM_STREAM_TYPE_DEFAULT; i < CAM_STREAM_TYPE_MAX; i++ ) {
+ List<struct QCameraMemory::QCameraMemInfo>::iterator it;
+ it = mPools[i].begin();
+ for( ; it != mPools[i].end() ; it++) {
+ QCameraMemory::deallocOneBuffer(*it);
+ }
+
+ mPools[i].clear();
+ }
+
+ pthread_mutex_unlock(&mLock);
+}
+
+/*===========================================================================
+ * FUNCTION : findBufferLocked
+ *
+ * DESCRIPTION: search for a appropriate cached buffer
+ *
+ * PARAMETERS :
+ * @memInfo : reference to struct that stores additional memory allocation info
+ * @heap_id : type of heap
+ * @size : size of the buffer
+ * @cached : whether the buffer should be cached
+ * @streaType: type of stream this buffer belongs to
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraMemoryPool::findBufferLocked(
+ struct QCameraMemory::QCameraMemInfo &memInfo, unsigned int heap_id,
+ size_t size, bool cached, cam_stream_type_t streamType)
+{
+ int rc = NAME_NOT_FOUND;
+
+ if (mPools[streamType].empty()) {
+ return NAME_NOT_FOUND;
+ }
+
+ List<struct QCameraMemory::QCameraMemInfo>::iterator it = mPools[streamType].begin();
+ if (streamType == CAM_STREAM_TYPE_OFFLINE_PROC) {
+ for( ; it != mPools[streamType].end() ; it++) {
+ if( ((*it).size == size) &&
+ ((*it).heap_id == heap_id) &&
+ ((*it).cached == cached) ) {
+ memInfo = *it;
+ LOGD("Found buffer %lx size %d",
+ (unsigned long)memInfo.handle, memInfo.size);
+ mPools[streamType].erase(it);
+ rc = NO_ERROR;
+ break;
+ }
+ }
+ } else {
+ for( ; it != mPools[streamType].end() ; it++) {
+ if(((*it).size >= size) &&
+ ((*it).heap_id == heap_id) &&
+ ((*it).cached == cached) ) {
+ memInfo = *it;
+ LOGD("Found buffer %lx size %d",
+ (unsigned long)memInfo.handle, memInfo.size);
+ mPools[streamType].erase(it);
+ rc = NO_ERROR;
+ break;
+ }
+ }
+ }
+
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : allocateBuffer
+ *
+ * DESCRIPTION: allocates a buffer from the memory pool,
+ * it will re-use cached buffers if possible
+ *
+ * PARAMETERS :
+ * @memInfo : reference to struct that stores additional memory allocation info
+ * @heap_id : type of heap
+ * @size : size of the buffer
+ * @cached : whether the buffer should be cached
+ * @streaType: type of stream this buffer belongs to
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraMemoryPool::allocateBuffer(
+ struct QCameraMemory::QCameraMemInfo &memInfo, unsigned int heap_id,
+ size_t size, bool cached, cam_stream_type_t streamType,
+ uint32_t secure_mode)
+{
+ int rc = NO_ERROR;
+
+ pthread_mutex_lock(&mLock);
+
+ rc = findBufferLocked(memInfo, heap_id, size, cached, streamType);
+ if (NAME_NOT_FOUND == rc ) {
+ LOGD("Buffer not found!");
+ rc = QCameraMemory::allocOneBuffer(memInfo, heap_id, size, cached,
+ secure_mode);
+ }
+
+ pthread_mutex_unlock(&mLock);
+
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : QCameraHeapMemory
+ *
+ * DESCRIPTION: constructor of QCameraHeapMemory for ion memory used internally in HAL
+ *
+ * PARAMETERS :
+ * @cached : flag indicates if using cached memory
+ *
+ * RETURN : none
+ *==========================================================================*/
+QCameraHeapMemory::QCameraHeapMemory(bool cached)
+ : QCameraMemory(cached)
+{
+ for (int i = 0; i < MM_CAMERA_MAX_NUM_FRAMES; i ++)
+ mPtr[i] = NULL;
+}
+
+/*===========================================================================
+ * FUNCTION : ~QCameraHeapMemory
+ *
+ * DESCRIPTION: deconstructor of QCameraHeapMemory
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+QCameraHeapMemory::~QCameraHeapMemory()
+{
+}
+
+/*===========================================================================
+ * FUNCTION : getPtr
+ *
+ * DESCRIPTION: return buffer pointer
+ *
+ * PARAMETERS :
+ * @index : index of the buffer
+ *
+ * RETURN : buffer ptr
+ *==========================================================================*/
+void *QCameraHeapMemory::getPtr(uint32_t index) const
+{
+ if (index >= mBufferCount) {
+ LOGE("index out of bound");
+ return (void *)BAD_INDEX;
+ }
+ return mPtr[index];
+}
+
+/*===========================================================================
+ * FUNCTION : allocate
+ *
+ * DESCRIPTION: allocate requested number of buffers of certain size
+ *
+ * PARAMETERS :
+ * @count : number of buffers to be allocated
+ * @size : lenght of the buffer to be allocated
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraHeapMemory::allocate(uint8_t count, size_t size, uint32_t isSecure)
+{
+ int rc = -1;
+ ATRACE_BEGIN_SNPRINTF("%s %zu %d", "HeapMemsize", size, count);
+ uint32_t heap_id_mask = 0x1 << ION_IOMMU_HEAP_ID;
+ if (isSecure == SECURE) {
+ rc = alloc(count, size, heap_id_mask, SECURE);
+ if (rc < 0) {
+ ATRACE_END();
+ return rc;
+ }
+ } else {
+ rc = alloc(count, size, heap_id_mask, NON_SECURE);
+ if (rc < 0) {
+ ATRACE_END();
+ return rc;
+ }
+
+ for (int i = 0; i < count; i ++) {
+ void *vaddr = mmap(NULL,
+ mMemInfo[i].size,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ mMemInfo[i].fd, 0);
+ if (vaddr == MAP_FAILED) {
+ for (int j = i-1; j >= 0; j --) {
+ munmap(mPtr[j], mMemInfo[j].size);
+ mPtr[j] = NULL;
+ deallocOneBuffer(mMemInfo[j]);
+ }
+ // Deallocate remaining buffers that have already been allocated
+ for (int j = i; j < count; j++) {
+ deallocOneBuffer(mMemInfo[j]);
+ }
+ ATRACE_END();
+ return NO_MEMORY;
+ } else
+ mPtr[i] = vaddr;
+ }
+ }
+ if (rc == 0) {
+ mBufferCount = count;
+ }
+ ATRACE_END();
+ return OK;
+}
+
+/*===========================================================================
+ * FUNCTION : allocateMore
+ *
+ * DESCRIPTION: allocate more requested number of buffers of certain size
+ *
+ * PARAMETERS :
+ * @count : number of buffers to be allocated
+ * @size : lenght of the buffer to be allocated
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraHeapMemory::allocateMore(uint8_t count, size_t size)
+{
+ ATRACE_BEGIN_SNPRINTF("%s %zu %d", "HeapMemsize", size, count);
+ unsigned int heap_id_mask = 0x1 << ION_IOMMU_HEAP_ID;
+ int rc = alloc(count, size, heap_id_mask, NON_SECURE);
+ if (rc < 0) {
+ ATRACE_END();
+ return rc;
+ }
+
+ for (int i = mBufferCount; i < count + mBufferCount; i ++) {
+ void *vaddr = mmap(NULL,
+ mMemInfo[i].size,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ mMemInfo[i].fd, 0);
+ if (vaddr == MAP_FAILED) {
+ for (int j = i-1; j >= mBufferCount; j --) {
+ munmap(mPtr[j], mMemInfo[j].size);
+ mPtr[j] = NULL;
+ deallocOneBuffer(mMemInfo[j]);
+ }
+ ATRACE_END();
+ return NO_MEMORY;
+ } else {
+ mPtr[i] = vaddr;
+ }
+ }
+ mBufferCount = (uint8_t)(mBufferCount + count);
+ ATRACE_END();
+ return OK;
+}
+
+/*===========================================================================
+ * FUNCTION : deallocate
+ *
+ * DESCRIPTION: deallocate buffers
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+void QCameraHeapMemory::deallocate()
+{
+ for (int i = 0; i < mBufferCount; i++) {
+ munmap(mPtr[i], mMemInfo[i].size);
+ mPtr[i] = NULL;
+ }
+ dealloc();
+ mBufferCount = 0;
+}
+
+/*===========================================================================
+ * FUNCTION : cacheOps
+ *
+ * DESCRIPTION: ion related memory cache operations
+ *
+ * PARAMETERS :
+ * @index : index of the buffer
+ * @cmd : cache ops command
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraHeapMemory::cacheOps(uint32_t index, unsigned int cmd)
+{
+ if (index >= mBufferCount)
+ return BAD_INDEX;
+ return cacheOpsInternal(index, cmd, mPtr[index]);
+}
+
+/*===========================================================================
+ * FUNCTION : getRegFlags
+ *
+ * DESCRIPTION: query initial reg flags
+ *
+ * PARAMETERS :
+ * @regFlags: initial reg flags of the allocated buffers
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraHeapMemory::getRegFlags(uint8_t * /*regFlags*/) const
+{
+ return INVALID_OPERATION;
+}
+
+/*===========================================================================
+ * FUNCTION : getMemory
+ *
+ * DESCRIPTION: get camera memory
+ *
+ * PARAMETERS :
+ * @index : buffer index
+ * @metadata: flag if it's metadata
+ *
+ * RETURN : camera memory ptr
+ * NULL if not supported or failed
+ *==========================================================================*/
+camera_memory_t *QCameraHeapMemory::getMemory(uint32_t /*index*/, bool /*metadata*/) const
+{
+ return NULL;
+}
+
+/*===========================================================================
+ * FUNCTION : getMatchBufIndex
+ *
+ * DESCRIPTION: query buffer index by opaque ptr
+ *
+ * PARAMETERS :
+ * @opaque : opaque ptr
+ * @metadata: flag if it's metadata
+ *
+ * RETURN : buffer index if match found,
+ * -1 if failed
+ *==========================================================================*/
+int QCameraHeapMemory::getMatchBufIndex(const void *opaque,
+ bool metadata) const
+{
+ int index = -1;
+ if (metadata) {
+ return -1;
+ }
+ for (int i = 0; i < mBufferCount; i++) {
+ if (mPtr[i] == opaque) {
+ index = i;
+ break;
+ }
+ }
+ return index;
+}
+
+/*===========================================================================
+ * FUNCTION : QCameraMetadataStreamMemory
+ *
+ * DESCRIPTION: constructor of QCameraMetadataStreamMemory
+ * for ion memory used internally in HAL for metadata
+ *
+ * PARAMETERS :
+ * @cached : flag indicates if using cached memory
+ *
+ * RETURN : none
+ *==========================================================================*/
+QCameraMetadataStreamMemory::QCameraMetadataStreamMemory(bool cached)
+ : QCameraHeapMemory(cached)
+{
+}
+
+/*===========================================================================
+ * FUNCTION : ~QCameraMetadataStreamMemory
+ *
+ * DESCRIPTION: destructor of QCameraMetadataStreamMemory
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+QCameraMetadataStreamMemory::~QCameraMetadataStreamMemory()
+{
+ if (mBufferCount > 0) {
+ LOGH("%s, buf_cnt > 0, deallocate buffers now.\n", __func__);
+ deallocate();
+ }
+}
+
+/*===========================================================================
+ * FUNCTION : getRegFlags
+ *
+ * DESCRIPTION: query initial reg flags
+ *
+ * PARAMETERS :
+ * @regFlags: initial reg flags of the allocated buffers
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraMetadataStreamMemory::getRegFlags(uint8_t *regFlags) const
+{
+ for (int i = 0; i < mBufferCount; i ++) {
+ regFlags[i] = 1;
+ }
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : QCameraStreamMemory
+ *
+ * DESCRIPTION: constructor of QCameraStreamMemory
+ * ION memory allocated directly from /dev/ion and shared with framework
+ *
+ * PARAMETERS :
+ * @memory : camera memory request ops table
+ * @cached : flag indicates if using cached memory
+ *
+ * RETURN : none
+ *==========================================================================*/
+QCameraStreamMemory::QCameraStreamMemory(camera_request_memory memory,
+ bool cached,
+ QCameraMemoryPool *pool,
+ cam_stream_type_t streamType, __unused cam_stream_buf_type bufType)
+ :QCameraMemory(cached, pool, streamType),
+ mGetMemory(memory)
+{
+ for (int i = 0; i < MM_CAMERA_MAX_NUM_FRAMES; i ++)
+ mCameraMemory[i] = NULL;
+}
+
+/*===========================================================================
+ * FUNCTION : ~QCameraStreamMemory
+ *
+ * DESCRIPTION: deconstructor of QCameraStreamMemory
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+QCameraStreamMemory::~QCameraStreamMemory()
+{
+}
+
+/*===========================================================================
+ * FUNCTION : allocate
+ *
+ * DESCRIPTION: allocate requested number of buffers of certain size
+ *
+ * PARAMETERS :
+ * @count : number of buffers to be allocated
+ * @size : lenght of the buffer to be allocated
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraStreamMemory::allocate(uint8_t count, size_t size, uint32_t isSecure)
+{
+ ATRACE_BEGIN_SNPRINTF("%s %zu %d", "StreamMemsize", size, count);
+ unsigned int heap_id_mask = 0x1 << ION_IOMMU_HEAP_ID;
+ int rc = alloc(count, size, heap_id_mask, isSecure);
+ if (rc < 0) {
+ ATRACE_END();
+ return rc;
+ }
+
+ for (int i = 0; i < count; i ++) {
+ if (isSecure == SECURE) {
+ mCameraMemory[i] = 0;
+ } else {
+ mCameraMemory[i] = mGetMemory(mMemInfo[i].fd, mMemInfo[i].size, 1, this);
+ }
+ }
+ mBufferCount = count;
+ ATRACE_END();
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : allocateMore
+ *
+ * DESCRIPTION: allocate more requested number of buffers of certain size
+ *
+ * PARAMETERS :
+ * @count : number of buffers to be allocated
+ * @size : lenght of the buffer to be allocated
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraStreamMemory::allocateMore(uint8_t count, size_t size)
+{
+ ATRACE_BEGIN_SNPRINTF("%s %zu %d", "StreamMemsize", size, count);
+ unsigned int heap_id_mask = 0x1 << ION_IOMMU_HEAP_ID;
+ int rc = alloc(count, size, heap_id_mask, NON_SECURE);
+ if (rc < 0) {
+ ATRACE_END();
+ return rc;
+ }
+
+ for (int i = mBufferCount; i < mBufferCount + count; i++) {
+ mCameraMemory[i] = mGetMemory(mMemInfo[i].fd, mMemInfo[i].size, 1, this);
+ }
+ mBufferCount = (uint8_t)(mBufferCount + count);
+ ATRACE_END();
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : deallocate
+ *
+ * DESCRIPTION: deallocate buffers
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+void QCameraStreamMemory::deallocate()
+{
+ for (int i = 0; i < mBufferCount; i ++) {
+ if (mCameraMemory[i])
+ mCameraMemory[i]->release(mCameraMemory[i]);
+ mCameraMemory[i] = NULL;
+ }
+ dealloc();
+ mBufferCount = 0;
+}
+
+/*===========================================================================
+ * FUNCTION : cacheOps
+ *
+ * DESCRIPTION: ion related memory cache operations
+ *
+ * PARAMETERS :
+ * @index : index of the buffer
+ * @cmd : cache ops command
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraStreamMemory::cacheOps(uint32_t index, unsigned int cmd)
+{
+ if (index >= mBufferCount)
+ return BAD_INDEX;
+ return cacheOpsInternal(index, cmd, mCameraMemory[index]->data);
+}
+
+/*===========================================================================
+ * FUNCTION : getRegFlags
+ *
+ * DESCRIPTION: query initial reg flags
+ *
+ * PARAMETERS :
+ * @regFlags: initial reg flags of the allocated buffers
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraStreamMemory::getRegFlags(uint8_t *regFlags) const
+{
+ for (int i = 0; i < mBufferCount; i ++)
+ regFlags[i] = 1;
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : getMemory
+ *
+ * DESCRIPTION: get camera memory
+ *
+ * PARAMETERS :
+ * @index : buffer index
+ * @metadata: flag if it's metadata
+ *
+ * RETURN : camera memory ptr
+ * NULL if not supported or failed
+ *==========================================================================*/
+camera_memory_t *QCameraStreamMemory::getMemory(uint32_t index,
+ bool metadata) const
+{
+ if (index >= mBufferCount || metadata)
+ return NULL;
+ return mCameraMemory[index];
+}
+
+/*===========================================================================
+ * FUNCTION : getMatchBufIndex
+ *
+ * DESCRIPTION: query buffer index by opaque ptr
+ *
+ * PARAMETERS :
+ * @opaque : opaque ptr
+ * @metadata: flag if it's metadata
+ *
+ * RETURN : buffer index if match found,
+ * -1 if failed
+ *==========================================================================*/
+int QCameraStreamMemory::getMatchBufIndex(const void *opaque,
+ bool metadata) const
+{
+ int index = -1;
+ if (metadata) {
+ return -1;
+ }
+ for (int i = 0; i < mBufferCount; i++) {
+ if (mCameraMemory[i]->data == opaque) {
+ index = i;
+ break;
+ }
+ }
+ return index;
+}
+
+/*===========================================================================
+ * FUNCTION : getPtr
+ *
+ * DESCRIPTION: return buffer pointer
+ *
+ * PARAMETERS :
+ * @index : index of the buffer
+ *
+ * RETURN : buffer ptr
+ *==========================================================================*/
+void *QCameraStreamMemory::getPtr(uint32_t index) const
+{
+ if (index >= mBufferCount) {
+ LOGE("index out of bound");
+ return (void *)BAD_INDEX;
+ }
+ if (mCameraMemory[index] == 0) {
+ return NULL;
+ }
+ return mCameraMemory[index]->data;
+}
+
+/*===========================================================================
+ * FUNCTION : QCameraVideoMemory
+ *
+ * DESCRIPTION: constructor of QCameraVideoMemory
+ * VideoStream buffers also include metadata buffers
+ *
+ * PARAMETERS :
+ * @memory : camera memory request ops table
+ * @cached : flag indicates if using cached ION memory
+ *
+ * RETURN : none
+ *==========================================================================*/
+QCameraVideoMemory::QCameraVideoMemory(camera_request_memory memory,
+ bool cached, QCameraMemType bufType)
+ : QCameraStreamMemory(memory, cached)
+{
+ memset(mMetadata, 0, sizeof(mMetadata));
+ memset(mNativeHandle, 0, sizeof(mNativeHandle));
+ mMetaBufCount = 0;
+ mBufType = bufType;
+ //Set Default color conversion format
+ mUsage = private_handle_t::PRIV_FLAGS_ITU_R_601_FR;
+
+ //Set Default frame format
+ mFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+}
+
+/*===========================================================================
+ * FUNCTION : ~QCameraVideoMemory
+ *
+ * DESCRIPTION: deconstructor of QCameraVideoMemory
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+QCameraVideoMemory::~QCameraVideoMemory()
+{
+}
+
+/*===========================================================================
+ * FUNCTION : allocate
+ *
+ * DESCRIPTION: allocate requested number of buffers of certain size
+ *
+ * PARAMETERS :
+ * @count : number of buffers to be allocated
+ * @size : lenght of the buffer to be allocated
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraVideoMemory::allocate(uint8_t count, size_t size, uint32_t isSecure)
+{
+ ATRACE_BEGIN_SNPRINTF("%s %zu %d", "VideoMemsize", size, count);
+ int rc = QCameraStreamMemory::allocate(count, size, isSecure);
+ if (rc < 0) {
+ ATRACE_END();
+ return rc;
+ }
+
+ if (!(mBufType & QCAMERA_MEM_TYPE_BATCH)) {
+ /*
+ * FDs = 1
+ * numInts = 5 //offset, size, usage, timestamp, format
+ */
+ rc = allocateMeta(count, 1, VIDEO_METADATA_NUM_INTS);
+ if (rc != NO_ERROR) {
+ ATRACE_END();
+ return rc;
+ }
+ for (int i = 0; i < count; i ++) {
+ native_handle_t *nh = mNativeHandle[i];
+ if (!nh) {
+ LOGE("Error in getting video native handle");
+ ATRACE_END();
+ return NO_MEMORY;
+ }
+ nh->data[0] = mMemInfo[i].fd;
+ nh->data[1] = 0;
+ nh->data[2] = (int)mMemInfo[i].size;
+ nh->data[3] = mUsage;
+ nh->data[4] = 0; //dummy value for timestamp in non-batch mode
+ nh->data[5] = mFormat;
+ }
+ }
+ mBufferCount = count;
+ ATRACE_END();
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : allocateMore
+ *
+ * DESCRIPTION: allocate more requested number of buffers of certain size
+ *
+ * PARAMETERS :
+ * @count : number of buffers to be allocated
+ * @size : lenght of the buffer to be allocated
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraVideoMemory::allocateMore(uint8_t count, size_t size)
+{
+ ATRACE_BEGIN_SNPRINTF("%s %zu %d", "VideoMemsize", size, count);
+ int rc = QCameraStreamMemory::allocateMore(count, size);
+ if (rc < 0) {
+ ATRACE_END();
+ return rc;
+ }
+
+ if (!(mBufType & QCAMERA_MEM_TYPE_BATCH)) {
+ for (int i = mBufferCount; i < count + mBufferCount; i ++) {
+ mMetadata[i] = mGetMemory(-1,
+ sizeof(media_metadata_buffer), 1, this);
+ if (!mMetadata[i]) {
+ LOGE("allocation of video metadata failed.");
+ for (int j = mBufferCount; j <= i-1; j ++) {
+ mMetadata[j]->release(mMetadata[j]);
+ mCameraMemory[j]->release(mCameraMemory[j]);
+ mCameraMemory[j] = NULL;
+ deallocOneBuffer(mMemInfo[j]);;
+ }
+ ATRACE_END();
+ return NO_MEMORY;
+ }
+ media_metadata_buffer * packet =
+ (media_metadata_buffer *)mMetadata[i]->data;
+ //FDs = 1
+ //numInts = 5 (offset, size, usage, timestamp, format)
+ mNativeHandle[i] = native_handle_create(1, VIDEO_METADATA_NUM_INTS);
+#ifdef USE_MEDIA_EXTENSIONS
+ packet->eType = kMetadataBufferTypeNativeHandleSource;
+ packet->pHandle = mNativeHandle[i];
+#else
+ packet->buffer_type = kMetadataBufferTypeCameraSource;
+ packet->meta_handle = mNativeHandle[i];
+#endif
+ native_handle_t *nh = mNativeHandle[i];
+ if (!nh) {
+ LOGE("Error in getting video native handle");
+ ATRACE_END();
+ return NO_MEMORY;
+ }
+ nh->data[0] = mMemInfo[i].fd;
+ nh->data[1] = 0;
+ nh->data[2] = (int)mMemInfo[i].size;
+ nh->data[3] = mUsage;
+ nh->data[4] = 0; //dummy value for timestamp in non-batch mode
+ nh->data[5] = mFormat;
+ }
+ }
+ mBufferCount = (uint8_t)(mBufferCount + count);
+ mMetaBufCount = mBufferCount;
+ ATRACE_END();
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : allocateMeta
+ *
+ * DESCRIPTION: allocate video encoder metadata structure
+ *
+ * PARAMETERS :
+ * @fd_cnt : Total FD count
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraVideoMemory::allocateMeta(uint8_t buf_cnt, int numFDs, int numInts)
+{
+ int rc = NO_ERROR;
+
+ for (int i = 0; i < buf_cnt; i++) {
+ mMetadata[i] = mGetMemory(-1,
+ sizeof(media_metadata_buffer), 1, this);
+ if (!mMetadata[i]) {
+ LOGE("allocation of video metadata failed.");
+ for (int j = (i - 1); j >= 0; j--) {
+ if (NULL != mNativeHandle[j]) {
+ native_handle_delete(mNativeHandle[j]);
+ }
+ mMetadata[j]->release(mMetadata[j]);
+ }
+ return NO_MEMORY;
+ }
+ media_metadata_buffer *packet =
+ (media_metadata_buffer *)mMetadata[i]->data;
+ mNativeHandle[i] = native_handle_create(numFDs, (numInts * numFDs));
+ if (mNativeHandle[i] == NULL) {
+ LOGE("Error in getting video native handle");
+ for (int j = (i - 1); j >= 0; j--) {
+ mMetadata[i]->release(mMetadata[i]);
+ if (NULL != mNativeHandle[j]) {
+ native_handle_delete(mNativeHandle[j]);
+ }
+ mMetadata[j]->release(mMetadata[j]);
+ }
+ return NO_MEMORY;
+ }
+#ifdef USE_MEDIA_EXTENSIONS
+ packet->eType = kMetadataBufferTypeNativeHandleSource;
+ packet->pHandle = mNativeHandle[i];
+#else
+ packet->buffer_type = kMetadataBufferTypeCameraSource;
+ packet->meta_handle = mNativeHandle[i];
+#endif
+ }
+ mMetaBufCount = buf_cnt;
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : deallocateMeta
+ *
+ * DESCRIPTION: deallocate video metadata buffers
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+void QCameraVideoMemory::deallocateMeta()
+{
+ for (int i = 0; i < mMetaBufCount; i++) {
+ native_handle_t *nh = mNativeHandle[i];
+ if (NULL != nh) {
+ if (native_handle_delete(nh)) {
+ LOGE("Unable to delete native handle");
+ }
+ } else {
+ LOGE("native handle not available");
+ }
+ mNativeHandle[i] = NULL;
+ mMetadata[i]->release(mMetadata[i]);
+ mMetadata[i] = NULL;
+ }
+ mMetaBufCount = 0;
+}
+
+
+/*===========================================================================
+ * FUNCTION : deallocate
+ *
+ * DESCRIPTION: deallocate buffers
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+void QCameraVideoMemory::deallocate()
+{
+ deallocateMeta();
+
+ QCameraStreamMemory::deallocate();
+ mBufferCount = 0;
+ mMetaBufCount = 0;
+}
+
+/*===========================================================================
+ * FUNCTION : getMemory
+ *
+ * DESCRIPTION: get camera memory
+ *
+ * PARAMETERS :
+ * @index : buffer index
+ * @metadata: flag if it's metadata
+ *
+ * RETURN : camera memory ptr
+ * NULL if not supported or failed
+ *==========================================================================*/
+camera_memory_t *QCameraVideoMemory::getMemory(uint32_t index,
+ bool metadata) const
+{
+ if (index >= mMetaBufCount || (!metadata && index >= mBufferCount))
+ return NULL;
+
+ if (metadata)
+ return mMetadata[index];
+ else
+ return mCameraMemory[index];
+}
+
+/*===========================================================================
+ * FUNCTION : updateNativeHandle
+ *
+ * DESCRIPTION: Updating native handle pointer
+ *
+ * PARAMETERS :
+ * @index : buffer index
+ * @metadata: flag if it's metadata
+ *
+ * RETURN : camera native handle ptr
+ * NULL if not supported or failed
+ *==========================================================================*/
+native_handle_t *QCameraVideoMemory::updateNativeHandle(uint32_t index, bool metadata)
+{
+ if (index >= mMetaBufCount || (!metadata && index >= mBufferCount)) {
+ return NULL;
+ }
+
+ native_handle_t *nh = NULL;
+ if (metadata && mMetadata[index] != NULL) {
+ media_metadata_buffer *packet =
+ (media_metadata_buffer *)mMetadata[index]->data;
+ nh = mNativeHandle[index];
+#ifdef USE_MEDIA_EXTENSIONS
+ packet->pHandle = nh;
+#else
+ packet->meta_handle = nh;
+#endif
+ }
+ return nh;
+}
+
+/*===========================================================================
+ * FUNCTION : closeNativeHandle
+ *
+ * DESCRIPTION: close video native handle
+ *
+ * PARAMETERS :
+ * @opaque : ptr to video frame to be returned
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraVideoMemory::closeNativeHandle(const void *data, bool metadata)
+{
+ int32_t rc = NO_ERROR;
+ int32_t index = -1;
+
+#ifdef USE_MEDIA_EXTENSIONS
+ camera_memory_t *video_mem = NULL;
+
+ if (metadata) {
+ index = getMatchBufIndex(data, metadata);
+ if (index < 0) {
+ LOGE("Invalid buffer");
+ return BAD_VALUE;
+ }
+ video_mem = getMemory(index, metadata);
+ media_metadata_buffer * packet = NULL;
+ if (video_mem) {
+ packet = (media_metadata_buffer *)video_mem->data;
+ }
+
+ if (packet != NULL && packet->eType ==
+ kMetadataBufferTypeNativeHandleSource) {
+ native_handle_close(packet->pHandle);
+ native_handle_delete(packet->pHandle);
+ packet->pHandle = NULL;
+ } else {
+ LOGE("Invalid Data. Could not release");
+ return BAD_VALUE;
+ }
+ } else {
+ LOGE("Not of type video meta buffer. Failed");
+ return BAD_VALUE;
+ }
+#endif
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : getMatchBufIndex
+ *
+ * DESCRIPTION: query buffer index by opaque ptr
+ *
+ * PARAMETERS :
+ * @opaque : opaque ptr
+ * @metadata: flag if it's metadata
+ *
+ * RETURN : buffer index if match found,
+ * -1 if failed
+ *==========================================================================*/
+int QCameraVideoMemory::getMatchBufIndex(const void *opaque,
+ bool metadata) const
+{
+ int index = -1;
+
+ if (metadata) {
+ for (int i = 0; i < mMetaBufCount; i++) {
+ if (mMetadata[i]->data == opaque) {
+ index = i;
+ break;
+ }
+ }
+ } else {
+ for (int i = 0; i < mBufferCount; i++) {
+ if (mCameraMemory[i]->data == opaque) {
+ index = i;
+ break;
+ }
+ }
+ }
+ return index;
+}
+
+/*===========================================================================
+ * FUNCTION : setVideoInfo
+ *
+ * DESCRIPTION: set native window gralloc ops table
+ *
+ * PARAMETERS :
+ * @usage : usage bit for video
+ *
+ * RETURN : none
+ *==========================================================================*/
+void QCameraVideoMemory::setVideoInfo(int usage, cam_format_t format)
+{
+ mUsage |= usage;
+ mFormat = convCamtoOMXFormat(format);
+}
+
+/*===========================================================================
+ * FUNCTION : convCamtoOMXFormat
+ *
+ * DESCRIPTION: map cam_format_t to corresponding OMX format
+ *
+ * PARAMETERS :
+ * @format : format in cam_format_t type
+ *
+ * RETURN : omx format
+ *==========================================================================*/
+int QCameraVideoMemory::convCamtoOMXFormat(cam_format_t format)
+{
+ int omxFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ switch (format) {
+ case CAM_FORMAT_YUV_420_NV21:
+ case CAM_FORMAT_YUV_420_NV21_VENUS:
+ case CAM_FORMAT_YUV_420_NV21_ADRENO:
+ omxFormat = QOMX_COLOR_FormatYVU420SemiPlanar;
+ break;
+ case CAM_FORMAT_YUV_420_NV12:
+ case CAM_FORMAT_YUV_420_NV12_VENUS:
+ omxFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ break;
+#ifndef VANILLA_HAL
+ case CAM_FORMAT_YUV_420_NV12_UBWC:
+ omxFormat = QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
+ break;
+#endif
+ default:
+ omxFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ }
+ return omxFormat;
+}
+
+/*===========================================================================
+ * FUNCTION : QCameraGrallocMemory
+ *
+ * DESCRIPTION: constructor of QCameraGrallocMemory
+ * preview stream buffers are allocated from gralloc native_windoe
+ *
+ * PARAMETERS :
+ * @memory : camera memory request ops table
+ *
+ * RETURN : none
+ *==========================================================================*/
+QCameraGrallocMemory::QCameraGrallocMemory(camera_request_memory memory)
+ : QCameraMemory(true), mColorSpace(ITU_R_601_FR)
+{
+ mMinUndequeuedBuffers = 0;
+ mMappableBuffers = 0;
+ mWindow = NULL;
+ mWidth = mHeight = mStride = mScanline = mUsage = 0;
+ mFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP;
+ mGetMemory = memory;
+ for (int i = 0; i < MM_CAMERA_MAX_NUM_FRAMES; i ++) {
+ mBufferHandle[i] = NULL;
+ mLocalFlag[i] = BUFFER_NOT_OWNED;
+ mPrivateHandle[i] = NULL;
+ }
+}
+
+/*===========================================================================
+ * FUNCTION : ~QCameraGrallocMemory
+ *
+ * DESCRIPTION: deconstructor of QCameraGrallocMemory
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+QCameraGrallocMemory::~QCameraGrallocMemory()
+{
+}
+
+/*===========================================================================
+ * FUNCTION : setWindowInfo
+ *
+ * DESCRIPTION: set native window gralloc ops table
+ *
+ * PARAMETERS :
+ * @window : gralloc ops table ptr
+ * @width : width of preview frame
+ * @height : height of preview frame
+ * @stride : stride of preview frame
+ * @scanline: scanline of preview frame
+ * @foramt : format of preview image
+ * @maxFPS : max fps of preview stream
+ * @usage : usage bit for gralloc
+ *
+ * RETURN : none
+ *==========================================================================*/
+void QCameraGrallocMemory::setWindowInfo(preview_stream_ops_t *window,
+ int width, int height, int stride, int scanline, int format, int maxFPS, int usage)
+{
+ mWindow = window;
+ mWidth = width;
+ mHeight = height;
+ mStride = stride;
+ mScanline = scanline;
+ mFormat = format;
+ mUsage = usage;
+ setMaxFPS(maxFPS);
+}
+
+/*===========================================================================
+ * FUNCTION : setMaxFPS
+ *
+ * DESCRIPTION: set max fps
+ *
+ * PARAMETERS :
+ * @maxFPS : max fps of preview stream
+ *
+ * RETURN : none
+ *==========================================================================*/
+void QCameraGrallocMemory::setMaxFPS(int maxFPS)
+{
+ /* input will be in multiples of 1000 */
+ maxFPS = (maxFPS + 500)/1000;
+
+ /* set the lower cap to 30 always, because we are not supporting runtime update of fps info
+ to display. Otherwise MDP may result in underruns (for example if initial fps is 15max and later
+ changed to 30).*/
+ if (maxFPS < 30) {
+ maxFPS = 30;
+ }
+
+ /* the new fps will be updated in metadata of the next frame enqueued to display*/
+ mMaxFPS = maxFPS;
+ LOGH("Setting max fps %d to display", mMaxFPS);
+}
+
+/*===========================================================================
+ * FUNCTION : displayBuffer
+ *
+ * DESCRIPTION: send received frame to display
+ *
+ * PARAMETERS :
+ * @index : index of preview frame
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraGrallocMemory::displayBuffer(uint32_t index)
+{
+ int err = NO_ERROR;
+ int dequeuedIdx = BAD_INDEX;
+
+ if (BUFFER_NOT_OWNED == mLocalFlag[index]) {
+ LOGE("buffer to be enqueued is not owned");
+ return INVALID_OPERATION;
+ }
+
+ err = mWindow->enqueue_buffer(mWindow, (buffer_handle_t *)mBufferHandle[index]);
+ if(err != 0) {
+ LOGE("enqueue_buffer failed, err = %d", err);
+ } else {
+ LOGD("enqueue_buffer hdl=%p", *mBufferHandle[index]);
+ mLocalFlag[index] = BUFFER_NOT_OWNED;
+ }
+
+ buffer_handle_t *buffer_handle = NULL;
+ int stride = 0;
+ err = mWindow->dequeue_buffer(mWindow, &buffer_handle, &stride);
+ if (err == NO_ERROR && buffer_handle != NULL) {
+ int i;
+ LOGD("dequed buf hdl =%p", *buffer_handle);
+ for(i = 0; i < mMappableBuffers; i++) {
+ if(mBufferHandle[i] == buffer_handle) {
+ LOGD("Found buffer in idx:%d", i);
+ mLocalFlag[i] = BUFFER_OWNED;
+ dequeuedIdx = i;
+ break;
+ }
+ }
+
+ if ((dequeuedIdx == BAD_INDEX) && (mMappableBuffers < mBufferCount)) {
+ dequeuedIdx = mMappableBuffers;
+ LOGD("Placing buffer in idx:%d", dequeuedIdx);
+ mBufferHandle[dequeuedIdx] = buffer_handle;
+ mLocalFlag[dequeuedIdx] = BUFFER_OWNED;
+
+ mPrivateHandle[dequeuedIdx] =
+ (struct private_handle_t *)(*mBufferHandle[dequeuedIdx]);
+ mMemInfo[dequeuedIdx].main_ion_fd = open("/dev/ion", O_RDONLY);
+ if (mMemInfo[dequeuedIdx].main_ion_fd < 0) {
+ LOGE("failed: could not open ion device");
+ return BAD_INDEX;
+ }
+
+ struct ion_fd_data ion_info_fd;
+ memset(&ion_info_fd, 0, sizeof(ion_info_fd));
+ ion_info_fd.fd = mPrivateHandle[dequeuedIdx]->fd;
+ if (ioctl(mMemInfo[dequeuedIdx].main_ion_fd,
+ ION_IOC_IMPORT, &ion_info_fd) < 0) {
+ LOGE("ION import failed\n");
+ return BAD_INDEX;
+ }
+
+ mCameraMemory[dequeuedIdx] =
+ mGetMemory(mPrivateHandle[dequeuedIdx]->fd,
+ (size_t)mPrivateHandle[dequeuedIdx]->size,
+ 1,
+ (void *)this);
+ LOGH("idx = %d, fd = %d, size = %d, offset = %d",
+ dequeuedIdx, mPrivateHandle[dequeuedIdx]->fd,
+ mPrivateHandle[dequeuedIdx]->size,
+ mPrivateHandle[dequeuedIdx]->offset);
+ mMemInfo[dequeuedIdx].fd = mPrivateHandle[dequeuedIdx]->fd;
+ mMemInfo[dequeuedIdx].size =
+ (size_t)mPrivateHandle[dequeuedIdx]->size;
+ mMemInfo[dequeuedIdx].handle = ion_info_fd.handle;
+
+ mMappableBuffers++;
+ }
+ } else {
+ LOGW("dequeue_buffer, no free buffer from display now");
+ }
+ return dequeuedIdx;
+}
+
+/*===========================================================================
+ * FUNCTION : enqueueBuffer
+ *
+ * DESCRIPTION: enqueue camera frame to display
+ *
+ * PARAMETERS :
+ * @index : index of frame
+ * @timeStamp : frame presentation time
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraGrallocMemory::enqueueBuffer(uint32_t index, nsecs_t timeStamp)
+{
+ int32_t err = NO_ERROR;
+
+ if (BUFFER_NOT_OWNED == mLocalFlag[index]) {
+ LOGE("buffer to be enqueued is not owned");
+ return INVALID_OPERATION;
+ }
+
+ if (timeStamp != 0) {
+ err = mWindow->set_timestamp(mWindow, timeStamp);
+ if (err != NO_ERROR){
+ LOGE("Failed to native window timestamp");
+ }
+ }
+
+ err = mWindow->enqueue_buffer(mWindow, (buffer_handle_t *)mBufferHandle[index]);
+ if(err != 0) {
+ LOGE("enqueue_buffer failed, err = %d", err);
+ } else {
+ LOGD("enqueue_buffer hdl=%p", *mBufferHandle[index]);
+ mLocalFlag[index] = BUFFER_NOT_OWNED;
+ }
+ return err;
+}
+
+/*===========================================================================
+ * FUNCTION : dequeueBuffer
+ *
+ * DESCRIPTION: receive a buffer from gralloc
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : int32_t
+ * NO_ERROR/Buffer index : Success
+ * < 0 failure code
+ *==========================================================================*/
+int32_t QCameraGrallocMemory::dequeueBuffer()
+{
+ int32_t err = NO_ERROR;
+ int32_t dequeuedIdx = BAD_INDEX;
+ buffer_handle_t *buffer_handle = NULL;
+ int32_t stride = 0;
+
+ dequeuedIdx = BAD_INDEX;
+ err = mWindow->dequeue_buffer(mWindow, &buffer_handle, &stride);
+ if ((err == NO_ERROR) && (buffer_handle != NULL)) {
+ int i;
+ LOGD("dequed buf hdl =%p", *buffer_handle);
+ for(i = 0; i < mMappableBuffers; i++) {
+ if(mBufferHandle[i] == buffer_handle) {
+ LOGD("Found buffer in idx:%d", i);
+ mLocalFlag[i] = BUFFER_OWNED;
+ dequeuedIdx = i;
+ break;
+ }
+ }
+
+ if ((dequeuedIdx == BAD_INDEX) &&
+ (mMappableBuffers < mBufferCount)) {
+ dequeuedIdx = mMappableBuffers;
+ LOGD("Placing buffer in idx:%d", dequeuedIdx);
+ mBufferHandle[dequeuedIdx] = buffer_handle;
+ mLocalFlag[dequeuedIdx] = BUFFER_OWNED;
+
+ mPrivateHandle[dequeuedIdx] =
+ (struct private_handle_t *)(*mBufferHandle[dequeuedIdx]);
+ //update max fps info
+ setMetaData(mPrivateHandle[dequeuedIdx], UPDATE_REFRESH_RATE, (void*)&mMaxFPS);
+ mMemInfo[dequeuedIdx].main_ion_fd = open("/dev/ion", O_RDONLY);
+ if (mMemInfo[dequeuedIdx].main_ion_fd < 0) {
+ LOGE("failed: could not open ion device");
+ return BAD_INDEX;
+ }
+
+ struct ion_fd_data ion_info_fd;
+ memset(&ion_info_fd, 0, sizeof(ion_info_fd));
+ ion_info_fd.fd = mPrivateHandle[dequeuedIdx]->fd;
+ if (ioctl(mMemInfo[dequeuedIdx].main_ion_fd,
+ ION_IOC_IMPORT, &ion_info_fd) < 0) {
+ LOGE("ION import failed\n");
+ return BAD_INDEX;
+ }
+
+ setMetaData(mPrivateHandle[dequeuedIdx], UPDATE_COLOR_SPACE,
+ &mColorSpace);
+ mCameraMemory[dequeuedIdx] =
+ mGetMemory(mPrivateHandle[dequeuedIdx]->fd,
+ (size_t)mPrivateHandle[dequeuedIdx]->size,
+ 1,
+ (void *)this);
+ LOGH("idx = %d, fd = %d, size = %d, offset = %d",
+ dequeuedIdx, mPrivateHandle[dequeuedIdx]->fd,
+ mPrivateHandle[dequeuedIdx]->size,
+ mPrivateHandle[dequeuedIdx]->offset);
+ mMemInfo[dequeuedIdx].fd = mPrivateHandle[dequeuedIdx]->fd;
+ mMemInfo[dequeuedIdx].size =
+ (size_t)mPrivateHandle[dequeuedIdx]->size;
+ mMemInfo[dequeuedIdx].handle = ion_info_fd.handle;
+
+ mMappableBuffers++;
+ }
+ } else {
+ LOGW("dequeue_buffer, no free buffer from display now");
+ }
+
+ return dequeuedIdx;
+}
+
+
+/*===========================================================================
+ * FUNCTION : allocate
+ *
+ * DESCRIPTION: allocate requested number of buffers of certain size
+ *
+ * PARAMETERS :
+ * @count : number of buffers to be allocated
+ * @size : lenght of the buffer to be allocated
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraGrallocMemory::allocate(uint8_t count, size_t /*size*/,
+ uint32_t /*isSecure*/)
+{
+ ATRACE_BEGIN_SNPRINTF("%s %d", "Grallocbufcnt", count);
+ int err = 0;
+ status_t ret = NO_ERROR;
+ int gralloc_usage = 0;
+ struct ion_fd_data ion_info_fd;
+ memset(&ion_info_fd, 0, sizeof(ion_info_fd));
+
+ LOGD("E ");
+
+ if (!mWindow) {
+ LOGE("Invalid native window");
+ ATRACE_END();
+ ret = INVALID_OPERATION;
+ goto end;
+ }
+
+ // Increment buffer count by min undequeued buffer.
+ err = mWindow->get_min_undequeued_buffer_count(mWindow,&mMinUndequeuedBuffers);
+ if (err != 0) {
+ LOGE("get_min_undequeued_buffer_count failed: %s (%d)",
+ strerror(-err), -err);
+ ret = UNKNOWN_ERROR;
+ goto end;
+ }
+
+ err = mWindow->set_buffer_count(mWindow, count);
+ if (err != 0) {
+ LOGE("set_buffer_count failed: %s (%d)",
+ strerror(-err), -err);
+ ret = UNKNOWN_ERROR;
+ goto end;
+ }
+
+ err = mWindow->set_buffers_geometry(mWindow, mWidth, mHeight, mFormat);
+ if (err != 0) {
+ LOGE("set_buffers_geometry failed: %s (%d)",
+ strerror(-err), -err);
+ ret = UNKNOWN_ERROR;
+ goto end;
+ }
+
+ gralloc_usage = GRALLOC_USAGE_HW_CAMERA_WRITE;
+ gralloc_usage |= mUsage;
+ err = mWindow->set_usage(mWindow, gralloc_usage);
+ if(err != 0) {
+ /* set_usage error out */
+ LOGE("set_usage rc = %d", err);
+ ret = UNKNOWN_ERROR;
+ goto end;
+ }
+ LOGH("usage = %d, geometry: %p, %d, %d, %d, %d, %d",
+ gralloc_usage, mWindow, mWidth, mHeight, mStride,
+ mScanline, mFormat);
+
+ mBufferCount = count;
+ if ((count < mMappableBuffers) || (mMappableBuffers == 0)) {
+ mMappableBuffers = count;
+ }
+
+ //Allocate cnt number of buffers from native window
+ for (int cnt = 0; cnt < mMappableBuffers; cnt++) {
+ int stride;
+ err = mWindow->dequeue_buffer(mWindow, &mBufferHandle[cnt], &stride);
+ if(!err) {
+ LOGD("dequeue buf hdl =%p", mBufferHandle[cnt]);
+ mLocalFlag[cnt] = BUFFER_OWNED;
+ } else {
+ mLocalFlag[cnt] = BUFFER_NOT_OWNED;
+ LOGE("dequeue_buffer idx = %d err = %d", cnt, err);
+ }
+
+ LOGD("dequeue buf: %p\n", mBufferHandle[cnt]);
+
+ if(err != 0) {
+ LOGE("dequeue_buffer failed: %s (%d)",
+ strerror(-err), -err);
+ ret = UNKNOWN_ERROR;
+ for(int i = 0; i < cnt; i++) {
+ // Deallocate buffers when the native window is gone
+ struct ion_handle_data ion_handle;
+ memset(&ion_handle, 0, sizeof(ion_handle));
+ ion_handle.handle = mMemInfo[i].handle;
+ if (ioctl(mMemInfo[i].main_ion_fd, ION_IOC_FREE, &ion_handle) < 0) {
+ ALOGE("ion free failed");
+ }
+ close(mMemInfo[i].main_ion_fd);
+
+ if(mLocalFlag[i] != BUFFER_NOT_OWNED) {
+ err = mWindow->cancel_buffer(mWindow, mBufferHandle[i]);
+ LOGH("cancel_buffer: hdl =%p", (*mBufferHandle[i]));
+ }
+ mLocalFlag[i] = BUFFER_NOT_OWNED;
+ mBufferHandle[i] = NULL;
+ }
+ reset();
+ goto end;
+ }
+
+ mPrivateHandle[cnt] =
+ (struct private_handle_t *)(*mBufferHandle[cnt]);
+ //update max fps info
+ setMetaData(mPrivateHandle[cnt], UPDATE_REFRESH_RATE, (void*)&mMaxFPS);
+ mMemInfo[cnt].main_ion_fd = open("/dev/ion", O_RDONLY);
+ if (mMemInfo[cnt].main_ion_fd < 0) {
+ LOGE("failed: could not open ion device");
+ for(int i = 0; i < cnt; i++) {
+ struct ion_handle_data ion_handle;
+ memset(&ion_handle, 0, sizeof(ion_handle));
+ ion_handle.handle = mMemInfo[i].handle;
+ if (ioctl(mMemInfo[i].main_ion_fd, ION_IOC_FREE, &ion_handle) < 0) {
+ LOGE("ion free failed");
+ }
+ close(mMemInfo[i].main_ion_fd);
+ if(mLocalFlag[i] != BUFFER_NOT_OWNED) {
+ err = mWindow->cancel_buffer(mWindow, mBufferHandle[i]);
+ LOGH("cancel_buffer: hdl =%p", (*mBufferHandle[i]));
+ }
+ mLocalFlag[i] = BUFFER_NOT_OWNED;
+ mBufferHandle[i] = NULL;
+ }
+ reset();
+ ret = UNKNOWN_ERROR;
+ goto end;
+ } else {
+ ion_info_fd.fd = mPrivateHandle[cnt]->fd;
+ if (ioctl(mMemInfo[cnt].main_ion_fd,
+ ION_IOC_IMPORT, &ion_info_fd) < 0) {
+ LOGE("ION import failed\n");
+ for(int i = 0; i < cnt; i++) {
+ struct ion_handle_data ion_handle;
+ memset(&ion_handle, 0, sizeof(ion_handle));
+ ion_handle.handle = mMemInfo[i].handle;
+ if (ioctl(mMemInfo[i].main_ion_fd, ION_IOC_FREE, &ion_handle) < 0) {
+ LOGE("ion free failed");
+ }
+ close(mMemInfo[i].main_ion_fd);
+
+ if(mLocalFlag[i] != BUFFER_NOT_OWNED) {
+ err = mWindow->cancel_buffer(mWindow, mBufferHandle[i]);
+ LOGH("cancel_buffer: hdl =%p", (*mBufferHandle[i]));
+ }
+ mLocalFlag[i] = BUFFER_NOT_OWNED;
+ mBufferHandle[i] = NULL;
+ }
+ close(mMemInfo[cnt].main_ion_fd);
+ reset();
+ ret = UNKNOWN_ERROR;
+ goto end;
+ }
+ }
+ setMetaData(mPrivateHandle[cnt], UPDATE_COLOR_SPACE, &mColorSpace);
+ mCameraMemory[cnt] =
+ mGetMemory(mPrivateHandle[cnt]->fd,
+ (size_t)mPrivateHandle[cnt]->size,
+ 1,
+ (void *)this);
+ LOGH("idx = %d, fd = %d, size = %d, offset = %d",
+ cnt, mPrivateHandle[cnt]->fd,
+ mPrivateHandle[cnt]->size,
+ mPrivateHandle[cnt]->offset);
+ mMemInfo[cnt].fd = mPrivateHandle[cnt]->fd;
+ mMemInfo[cnt].size = (size_t)mPrivateHandle[cnt]->size;
+ mMemInfo[cnt].handle = ion_info_fd.handle;
+ }
+
+ //Cancel min_undequeued_buffer buffers back to the window
+ for (int i = 0; i < mMinUndequeuedBuffers; i ++) {
+ err = mWindow->cancel_buffer(mWindow, mBufferHandle[i]);
+ mLocalFlag[i] = BUFFER_NOT_OWNED;
+ }
+
+end:
+ if (ret != NO_ERROR) {
+ mMappableBuffers = 0;
+ }
+ LOGD("X ");
+ ATRACE_END();
+ return ret;
+}
+
+
+/*===========================================================================
+ * FUNCTION : allocateMore
+ *
+ * DESCRIPTION: allocate more requested number of buffers of certain size
+ *
+ * PARAMETERS :
+ * @count : number of buffers to be allocated
+ * @size : lenght of the buffer to be allocated
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraGrallocMemory::allocateMore(uint8_t /*count*/, size_t /*size*/)
+{
+ LOGE("Not implenmented yet");
+ return UNKNOWN_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : deallocate
+ *
+ * DESCRIPTION: deallocate buffers
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+void QCameraGrallocMemory::deallocate()
+{
+ LOGD("E ", __FUNCTION__);
+
+ for (int cnt = 0; cnt < mMappableBuffers; cnt++) {
+ mCameraMemory[cnt]->release(mCameraMemory[cnt]);
+ struct ion_handle_data ion_handle;
+ memset(&ion_handle, 0, sizeof(ion_handle));
+ ion_handle.handle = mMemInfo[cnt].handle;
+ if (ioctl(mMemInfo[cnt].main_ion_fd, ION_IOC_FREE, &ion_handle) < 0) {
+ LOGE("ion free failed");
+ }
+ close(mMemInfo[cnt].main_ion_fd);
+ if(mLocalFlag[cnt] != BUFFER_NOT_OWNED) {
+ if (mWindow) {
+ mWindow->cancel_buffer(mWindow, mBufferHandle[cnt]);
+ LOGH("cancel_buffer: hdl =%p", (*mBufferHandle[cnt]));
+ } else {
+ LOGE("Preview window is NULL, cannot cancel_buffer: hdl =%p",
+ (*mBufferHandle[cnt]));
+ }
+ }
+ mLocalFlag[cnt] = BUFFER_NOT_OWNED;
+ LOGH("put buffer %d successfully", cnt);
+ }
+ mBufferCount = 0;
+ mMappableBuffers = 0;
+ LOGD("X ",__FUNCTION__);
+}
+
+/*===========================================================================
+ * FUNCTION : cacheOps
+ *
+ * DESCRIPTION: ion related memory cache operations
+ *
+ * PARAMETERS :
+ * @index : index of the buffer
+ * @cmd : cache ops command
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraGrallocMemory::cacheOps(uint32_t index, unsigned int cmd)
+{
+ if (index >= mMappableBuffers)
+ return BAD_INDEX;
+ return cacheOpsInternal(index, cmd, mCameraMemory[index]->data);
+}
+
+/*===========================================================================
+ * FUNCTION : getRegFlags
+ *
+ * DESCRIPTION: query initial reg flags
+ *
+ * PARAMETERS :
+ * @regFlags: initial reg flags of the allocated buffers
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraGrallocMemory::getRegFlags(uint8_t *regFlags) const
+{
+ int i = 0;
+ for (i = 0; i < mMinUndequeuedBuffers; i ++)
+ regFlags[i] = 0;
+ for (; i < mMappableBuffers; i ++)
+ regFlags[i] = 1;
+ for (; i < mBufferCount; i ++)
+ regFlags[i] = 0;
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : getMemory
+ *
+ * DESCRIPTION: get camera memory
+ *
+ * PARAMETERS :
+ * @index : buffer index
+ * @metadata: flag if it's metadata
+ *
+ * RETURN : camera memory ptr
+ * NULL if not supported or failed
+ *==========================================================================*/
+camera_memory_t *QCameraGrallocMemory::getMemory(uint32_t index,
+ bool metadata) const
+{
+ if (index >= mMappableBuffers || metadata)
+ return NULL;
+ return mCameraMemory[index];
+}
+
+/*===========================================================================
+ * FUNCTION : getMatchBufIndex
+ *
+ * DESCRIPTION: query buffer index by opaque ptr
+ *
+ * PARAMETERS :
+ * @opaque : opaque ptr
+ * @metadata: flag if it's metadata
+ *
+ * RETURN : buffer index if match found,
+ * -1 if failed
+ *==========================================================================*/
+int QCameraGrallocMemory::getMatchBufIndex(const void *opaque,
+ bool metadata) const
+{
+ int index = -1;
+ if (metadata) {
+ return -1;
+ }
+ for (int i = 0; i < mMappableBuffers; i++) {
+ if (mCameraMemory[i]->data == opaque) {
+ index = i;
+ break;
+ }
+ }
+ return index;
+}
+
+/*===========================================================================
+ * FUNCTION : getPtr
+ *
+ * DESCRIPTION: return buffer pointer
+ *
+ * PARAMETERS :
+ * @index : index of the buffer
+ *
+ * RETURN : buffer ptr
+ *==========================================================================*/
+void *QCameraGrallocMemory::getPtr(uint32_t index) const
+{
+ if (index >= mMappableBuffers) {
+ LOGE("index out of bound");
+ return (void *)BAD_INDEX;
+ }
+ return mCameraMemory[index]->data;
+}
+
+/*===========================================================================
+ * FUNCTION : setMappable
+ *
+ * DESCRIPTION: configure the number of buffers ready to map
+ *
+ * PARAMETERS :
+ * @mappable : the number of desired mappable buffers
+ *
+ * RETURN : none
+ *==========================================================================*/
+void QCameraGrallocMemory::setMappable(uint8_t mappable)
+{
+ if (mMappableBuffers == 0) {
+ mMappableBuffers = mappable;
+ }
+}
+
+/*===========================================================================
+ * FUNCTION : getMappable
+ *
+ * DESCRIPTION: query number of buffers already allocated
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : number of buffers already allocated
+ *==========================================================================*/
+uint8_t QCameraGrallocMemory::getMappable() const
+{
+ return mMappableBuffers;
+}
+
+/*===========================================================================
+ * FUNCTION : checkIfAllBuffersMapped
+ *
+ * DESCRIPTION: check if all buffers for the are mapped
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : 1 if all buffers mapped
+ * 0 if total buffers not equal to mapped buffers
+ *==========================================================================*/
+uint8_t QCameraGrallocMemory::checkIfAllBuffersMapped() const
+{
+ LOGH("mBufferCount: %d, mMappableBuffers: %d",
+ mBufferCount, mMappableBuffers);
+ return (mBufferCount == mMappableBuffers);
+}
+
+
+}; //namespace qcamera