QCamera2: Add memory pools for stream buffers
Add the necessary functionality for caching
stream buffers in memory pools for each
stream type. The buffers will be re-used
as long as the camera client doesn't trigger
internal preview restart by updating the
use case(zsl vs. non-zsl), picture size etc.
CRs-Fixed: 571777
Change-Id: I6097662ef2206016f512a3406ce1860fce44d5ef
diff --git a/QCamera2/HAL/QCamera2HWI.cpp b/QCamera2/HAL/QCamera2HWI.cpp
index cd1b820..244ecd0 100644
--- a/QCamera2/HAL/QCamera2HWI.cpp
+++ b/QCamera2/HAL/QCamera2HWI.cpp
@@ -1564,7 +1564,10 @@
case CAM_STREAM_TYPE_PREVIEW:
{
if (isNoDisplayMode()) {
- mem = new QCameraStreamMemory(mGetMemory, bCachedMem);
+ mem = new QCameraStreamMemory(mGetMemory,
+ bCachedMem,
+ &m_memoryPool,
+ stream_type);
} else {
cam_dimension_t dim;
QCameraGrallocMemory *grallocMemory =
@@ -1605,7 +1608,10 @@
case CAM_STREAM_TYPE_RAW:
case CAM_STREAM_TYPE_METADATA:
case CAM_STREAM_TYPE_OFFLINE_PROC:
- mem = new QCameraStreamMemory(mGetMemory, bCachedMem);
+ mem = new QCameraStreamMemory(mGetMemory,
+ bCachedMem,
+ &m_memoryPool,
+ stream_type);
break;
case CAM_STREAM_TYPE_VIDEO:
{
diff --git a/QCamera2/HAL/QCamera2HWI.h b/QCamera2/HAL/QCamera2HWI.h
index f459d69..5f18f52 100644
--- a/QCamera2/HAL/QCamera2HWI.h
+++ b/QCamera2/HAL/QCamera2HWI.h
@@ -45,6 +45,7 @@
#include "QCameraAllocator.h"
#include "QCameraPostProc.h"
#include "QCameraThermalAdapter.h"
+#include "QCameraMem.h"
extern "C" {
#include <mm_camera_interface.h>
@@ -481,6 +482,7 @@
pthread_mutex_t m_lock;
pthread_cond_t m_cond;
qcamera_api_result_t m_apiResult;
+ QCameraMemoryPool m_memoryPool;
pthread_mutex_t m_evtLock;
pthread_cond_t m_evtCond;
diff --git a/QCamera2/HAL/QCameraMem.cpp b/QCamera2/HAL/QCameraMem.cpp
index 8c09e6b..53a2b14 100644
--- a/QCamera2/HAL/QCameraMem.cpp
+++ b/QCamera2/HAL/QCameraMem.cpp
@@ -58,8 +58,12 @@
*
* RETURN : None
*==========================================================================*/
-QCameraMemory::QCameraMemory(bool cached)
- :m_bCached(cached)
+QCameraMemory::QCameraMemory(bool cached,
+ QCameraMemoryPool *pool,
+ cam_stream_type_t streamType)
+ :m_bCached(cached),
+ mMemoryPool(pool),
+ mStreamType(streamType)
{
mBufferCount = 0;
memset(mMemInfo, 0, sizeof(mMemInfo));
@@ -251,13 +255,30 @@
}
for (int i = mBufferCount; i < new_bufCnt; i ++) {
- rc = allocOneBuffer(mMemInfo[i], heap_id, size);
- if (rc < 0) {
- ALOGE("%s: AllocateIonMemory failed", __func__);
- for (int j = i-1; j >= mBufferCount; j--)
- deallocOneBuffer(mMemInfo[j]);
- break;
+ if ( NULL == mMemoryPool ) {
+ ALOGE("%s : No memory pool available", __func__);
+ rc = allocOneBuffer(mMemInfo[i], heap_id, size, m_bCached);
+ if (rc < 0) {
+ ALOGE("%s: AllocateIonMemory failed", __func__);
+ for (int j = i-1; j >= 0; j--)
+ deallocOneBuffer(mMemInfo[j]);
+ break;
+ }
+ } else {
+ rc = mMemoryPool->allocateBuffer(mMemInfo[i],
+ heap_id,
+ size,
+ m_bCached,
+ mStreamType);
+ if (rc < 0) {
+ ALOGE("%s: Memory pool allocation failed", __func__);
+ for (int j = i-1; j >= 0; j--)
+ mMemoryPool->releaseBuffer(mMemInfo[j],
+ mStreamType);
+ break;
+ }
}
+
}
return rc;
}
@@ -273,8 +294,13 @@
*==========================================================================*/
void QCameraMemory::dealloc()
{
- for (int i = 0; i < mBufferCount; i++)
- deallocOneBuffer(mMemInfo[i]);
+ for (int i = 0; i < mBufferCount; i++) {
+ if ( NULL == mMemoryPool ) {
+ deallocOneBuffer(mMemInfo[i]);
+ } else {
+ mMemoryPool->releaseBuffer(mMemInfo[i], mStreamType);
+ }
+ }
}
/*===========================================================================
@@ -286,12 +312,16 @@
* @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, int heap_id, int size)
+int QCameraMemory::allocOneBuffer(QCameraMemInfo &memInfo,
+ int heap_id,
+ int size,
+ bool cached)
{
int rc = OK;
struct ion_handle_data handle_data;
@@ -310,7 +340,7 @@
/* to make it page size aligned */
alloc.len = (alloc.len + 4095) & (~4095);
alloc.align = 4096;
- if (m_bCached) {
+ if (cached) {
alloc.flags = ION_FLAG_CACHED;
}
alloc.heap_mask = heap_id;
@@ -332,6 +362,11 @@
memInfo.fd = ion_info_fd.fd;
memInfo.handle = ion_info_fd.handle;
memInfo.size = alloc.len;
+ memInfo.cached = cached;
+ memInfo.heap_id = heap_id;
+
+ ALOGD("%s : ION buffer %p with size %d allocated",
+ __func__, memInfo.handle, size);
return OK;
ION_MAP_FAILED:
@@ -375,6 +410,168 @@
}
/*===========================================================================
+ * 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 = 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,
+ int heap_id,
+ uint32_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();
+ for( ; it != mPools[streamType].end() ; it++) {
+ if( ((*it).size >= size) &&
+ ((*it).heap_id == heap_id) &&
+ ((*it).cached == cached) ) {
+ memInfo = *it;
+ ALOGE("%s : Found buffer %p size %d",
+ __func__, 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,
+ int heap_id,
+ int size,
+ bool cached,
+ cam_stream_type_t streamType)
+{
+ int rc = NO_ERROR;
+
+ pthread_mutex_lock(&mLock);
+
+ rc = findBufferLocked(memInfo, heap_id, size, cached, streamType);
+ if (NAME_NOT_FOUND == rc ) {
+ ALOGE("%s : Buffer not found!", __func__);
+ rc = QCameraMemory::allocOneBuffer(memInfo, heap_id, size, cached);
+ }
+
+ pthread_mutex_unlock(&mLock);
+
+ return rc;
+}
+
+/*===========================================================================
* FUNCTION : QCameraHeapMemory
*
* DESCRIPTION: constructor of QCameraHeapMemory for ion memory used internally in HAL
@@ -620,8 +817,10 @@
* RETURN : none
*==========================================================================*/
QCameraStreamMemory::QCameraStreamMemory(camera_request_memory getMemory,
- bool cached)
- :QCameraMemory(cached),
+ bool cached,
+ QCameraMemoryPool *pool,
+ cam_stream_type_t streamType)
+ :QCameraMemory(cached, pool, streamType),
mGetMemory(getMemory)
{
for (int i = 0; i < MM_CAMERA_MAX_NUM_FRAMES; i ++)
@@ -1163,7 +1362,7 @@
struct ion_fd_data ion_info_fd;
memset(&ion_info_fd, 0, sizeof(ion_info_fd));
- ALOGI(" %s : E ", __FUNCTION__);
+ ALOGD(" %s : E ", __func__);
if (!mWindow) {
ALOGE("Invalid native window");
@@ -1325,7 +1524,7 @@
}
end:
- ALOGI(" %s : X ",__func__);
+ ALOGD(" %s : X ",__func__);
return ret;
}
diff --git a/QCamera2/HAL/QCameraMem.h b/QCamera2/HAL/QCameraMem.h
index 1dee2cd..18a2a24 100644
--- a/QCamera2/HAL/QCameraMem.h
+++ b/QCamera2/HAL/QCameraMem.h
@@ -32,6 +32,7 @@
#include <hardware/camera.h>
#include <utils/Mutex.h>
+#include <utils/List.h>
extern "C" {
#include <sys/types.h>
@@ -41,6 +42,8 @@
namespace qcamera {
+class QCameraMemoryPool;
+
// Base class for all memory types. Abstract.
class QCameraMemory {
@@ -61,29 +64,69 @@
virtual int getMatchBufIndex(const void *opaque, bool metadata) const = 0;
virtual void *getPtr(int index) const= 0;
- QCameraMemory(bool cached);
+ QCameraMemory(bool cached,
+ QCameraMemoryPool *pool = NULL,
+ cam_stream_type_t streamType = CAM_STREAM_TYPE_DEFAULT);
virtual ~QCameraMemory();
void getBufDef(const cam_frame_len_offset_t &offset,
mm_camera_buf_def_t &bufDef, int index) const;
protected:
+
+ friend class QCameraMemoryPool;
+
struct QCameraMemInfo {
int fd;
int main_ion_fd;
struct ion_handle *handle;
uint32_t size;
+ bool cached;
+ int heap_id;
};
int alloc(int count, int size, int heap_id);
void dealloc();
- int allocOneBuffer(struct QCameraMemInfo &memInfo, int heap_id, int size);
- void deallocOneBuffer(struct QCameraMemInfo &memInfo);
+ static int allocOneBuffer(struct QCameraMemInfo &memInfo,
+ int heap_id,
+ int size,
+ bool cached);
+ static void deallocOneBuffer(struct QCameraMemInfo &memInfo);
int cacheOpsInternal(int index, unsigned int cmd, void *vaddr);
bool m_bCached;
int mBufferCount;
struct QCameraMemInfo mMemInfo[MM_CAMERA_MAX_NUM_FRAMES];
+ QCameraMemoryPool *mMemoryPool;
+ cam_stream_type_t mStreamType;
+};
+
+class QCameraMemoryPool {
+
+public:
+
+ QCameraMemoryPool();
+ virtual ~QCameraMemoryPool();
+
+ int allocateBuffer(struct QCameraMemory::QCameraMemInfo &memInfo,
+ int heap_id,
+ int size,
+ bool cached,
+ cam_stream_type_t streamType);
+ void releaseBuffer(struct QCameraMemory::QCameraMemInfo &memInfo,
+ cam_stream_type_t streamType);
+ void clear();
+
+protected:
+
+ int findBufferLocked(struct QCameraMemory::QCameraMemInfo &memInfo,
+ int heap_id,
+ uint32_t size,
+ bool cached,
+ cam_stream_type_t streamType);
+
+ android::List<QCameraMemory::QCameraMemInfo> mPools[CAM_STREAM_TYPE_MAX];
+ pthread_mutex_t mLock;
};
// Internal heap memory is used for memories used internally
@@ -110,7 +153,10 @@
// framework. They are allocated from /dev/ion or gralloc.
class QCameraStreamMemory : public QCameraMemory {
public:
- QCameraStreamMemory(camera_request_memory getMemory, bool cached);
+ QCameraStreamMemory(camera_request_memory getMemory,
+ bool cached,
+ QCameraMemoryPool *pool = NULL,
+ cam_stream_type_t streamType = CAM_STREAM_TYPE_DEFAULT);
virtual ~QCameraStreamMemory();
virtual int allocate(int count, int size);
diff --git a/QCamera2/HAL/QCameraStateMachine.cpp b/QCamera2/HAL/QCameraStateMachine.cpp
index f90e24e..2b4f149 100644
--- a/QCamera2/HAL/QCameraStateMachine.cpp
+++ b/QCamera2/HAL/QCameraStateMachine.cpp
@@ -352,6 +352,10 @@
{
bool needRestart = false;
rc = m_parent->updateParameters((char*)payload, needRestart);
+ if (needRestart) {
+ // Clear memory pools
+ m_parent->m_memoryPool.clear();
+ }
if (rc == NO_ERROR) {
rc = m_parent->commitParameterChanges();
}
@@ -670,6 +674,8 @@
if (needRestart) {
// need restart preview for parameters to take effect
m_parent->unpreparePreview();
+ // Clear memory pools
+ m_parent->m_memoryPool.clear();
// commit parameter changes to server
m_parent->commitParameterChanges();
// prepare preview again
@@ -953,6 +959,8 @@
// need restart preview for parameters to take effect
// stop preview
m_parent->stopPreview();
+ // Clear memory pools
+ m_parent->m_memoryPool.clear();
// commit parameter changes to server
m_parent->commitParameterChanges();
// start preview again
@@ -2494,6 +2502,8 @@
// need restart preview for parameters to take effect
// stop preview
m_parent->stopPreview();
+ // Clear memory pools
+ m_parent->m_memoryPool.clear();
// commit parameter changes to server
m_parent->commitParameterChanges();
// start preview again