blob: 7310073a7ab98ba83f671a7a892cebd508a0ff95 [file] [log] [blame]
/*
* Copyright 2013, Samsung Electronics Co. LTD
*
* 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 toggle 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.
*/
#define LOG_TAG "ExynosCameraBufferManager"
#include "ExynosCameraBufferManager.h"
namespace android {
ExynosCameraBufferManager::ExynosCameraBufferManager()
{
m_isDestructor = false;
m_cameraId = 0;
init();
m_allocationThread = new allocThread(this, &ExynosCameraBufferManager::m_allocationThreadFunc, "allocationThreadFunc");
}
ExynosCameraBufferManager::~ExynosCameraBufferManager()
{
m_isDestructor = true;
}
ExynosCameraBufferManager *ExynosCameraBufferManager::createBufferManager(buffer_manager_type_t type)
{
switch (type) {
case BUFFER_MANAGER_ION_TYPE:
return (ExynosCameraBufferManager *)new InternalExynosCameraBufferManager();
break;
case BUFFER_MANAGER_HEAP_BASE_TYPE:
return (ExynosCameraBufferManager *)new MHBExynosCameraBufferManager();
break;
case BUFFER_MANAGER_GRALLOC_TYPE:
return (ExynosCameraBufferManager *)new GrallocExynosCameraBufferManager();
break;
case BUFFER_MANAGER_SERVICE_GRALLOC_TYPE:
return (ExynosCameraBufferManager *)new ServiceExynosCameraBufferManager();
break;
case BUFFER_MANAGER_INVALID_TYPE:
CLOGE2("Unknown bufferManager type(%d)", (int)type);
default:
break;
}
return NULL;
}
status_t ExynosCameraBufferManager::create(const char *name, int cameraId, void *defaultAllocator)
{
Mutex::Autolock lock(m_lock);
status_t ret = NO_ERROR;
m_cameraId = cameraId;
strncpy(m_name, name, EXYNOS_CAMERA_NAME_STR_SIZE - 1);
if (defaultAllocator == NULL) {
if (m_createDefaultAllocator(false) != NO_ERROR) {
CLOGE("m_createDefaultAllocator failed");
return INVALID_OPERATION;
}
} else {
if (m_setDefaultAllocator(defaultAllocator) != NO_ERROR) {
CLOGE("m_setDefaultAllocator failed");
return INVALID_OPERATION;
}
}
return ret;
}
status_t ExynosCameraBufferManager::create(const char *name, void *defaultAllocator)
{
return create(name, 0, defaultAllocator);
}
void ExynosCameraBufferManager::init(void)
{
EXYNOS_CAMERA_BUFFER_IN();
m_flagAllocated = false;
m_reservedMemoryCount = 0;
m_reqBufCount = 0;
m_allocatedBufCount = 0;
m_allowedMaxBufCount = 0;
m_defaultAllocator = NULL;
m_isCreateDefaultAllocator = false;
memset((void *)m_buffer, 0, (VIDEO_MAX_FRAME) * sizeof(struct ExynosCameraBuffer));
for (int bufIndex = 0; bufIndex < VIDEO_MAX_FRAME; bufIndex++) {
for (int planeIndex = 0; planeIndex < EXYNOS_CAMERA_BUFFER_MAX_PLANES; planeIndex++) {
m_buffer[bufIndex].fd[planeIndex] = -1;
}
}
m_hasMetaPlane = false;
memset(m_name, 0x00, sizeof(m_name));
strncpy(m_name, "none", EXYNOS_CAMERA_NAME_STR_SIZE - 1);
m_flagSkipAllocation = false;
m_flagNeedMmap = false;
m_allocMode = BUFFER_MANAGER_ALLOCATION_ATONCE;
m_indexOffset = 0;
m_graphicBufferAllocator.init();
EXYNOS_CAMERA_BUFFER_OUT();
}
void ExynosCameraBufferManager::deinit(void)
{
if (m_flagAllocated == false) {
CLOGI("OUT.. Buffer is not allocated");
return;
}
CLOGD("IN..");
if (m_allocMode == BUFFER_MANAGER_ALLOCATION_SILENT) {
m_allocationThread->join();
CLOGI("allocationThread is finished");
}
for (int bufIndex = 0; bufIndex < m_allocatedBufCount; bufIndex++)
cancelBuffer(bufIndex);
if (m_free() != NO_ERROR)
CLOGE("free failed");
if (m_defaultAllocator != NULL && m_isCreateDefaultAllocator == true) {
delete m_defaultAllocator;
m_defaultAllocator = NULL;
}
m_reservedMemoryCount = 0;
m_flagSkipAllocation = false;
CLOGD("OUT..");
}
status_t ExynosCameraBufferManager::resetBuffers(void)
{
/* same as deinit */
/* clear buffers except releasing the memory */
status_t ret = NO_ERROR;
if (m_flagAllocated == false) {
CLOGI("OUT.. Buffer is not allocated");
return ret;
}
CLOGD("IN..");
if (m_allocMode == BUFFER_MANAGER_ALLOCATION_SILENT) {
m_allocationThread->join();
CLOGI("allocationThread is finished");
}
for (int bufIndex = m_indexOffset; bufIndex < m_allocatedBufCount + m_indexOffset; bufIndex++)
cancelBuffer(bufIndex);
m_resetSequenceQ();
m_flagSkipAllocation = true;
return ret;
}
status_t ExynosCameraBufferManager::setAllocator(void *allocator)
{
Mutex::Autolock lock(m_lock);
if (allocator == NULL) {
CLOGE("m_allocator equals NULL");
return INVALID_OPERATION;
}
return m_setAllocator(allocator);
}
status_t ExynosCameraBufferManager::alloc(void)
{
EXYNOS_CAMERA_BUFFER_IN();
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
Mutex::Autolock lock(m_lock);
status_t ret = NO_ERROR;
if (m_flagSkipAllocation == true) {
CLOGI("skip to allocate memory (m_flagSkipAllocation=%d)",
(int)m_flagSkipAllocation);
goto func_exit;
}
if (m_checkInfoForAlloc() == false) {
CLOGE("m_checkInfoForAlloc failed");
ret = INVALID_OPERATION;
goto func_exit;
}
if (m_hasMetaPlane == true) {
if (m_defaultAlloc(m_indexOffset, m_reqBufCount + m_indexOffset, m_hasMetaPlane) != NO_ERROR) {
CLOGE("m_defaultAlloc failed");
ret = INVALID_OPERATION;
goto func_exit;
}
}
/* allocate image buffer */
if (m_alloc(m_indexOffset, m_reqBufCount + m_indexOffset) != NO_ERROR) {
CLOGE("m_alloc failed");
if (m_hasMetaPlane == true) {
CLOGD("Free metadata plane. bufferCount %d",
m_reqBufCount);
if (m_defaultFree(m_indexOffset, m_reqBufCount + m_indexOffset, m_hasMetaPlane) != NO_ERROR) {
CLOGE("m_defaultFree failed");
}
}
ret = INVALID_OPERATION;
goto func_exit;
}
m_allocatedBufCount = m_reqBufCount;
m_resetSequenceQ();
m_flagAllocated = true;
CLOGD("Allocate the buffer succeeded (allowed(%d), requested(%d), allocated(%d))",
m_allowedMaxBufCount, m_reqBufCount, m_allocatedBufCount);
dumpBufferInfo();
if (m_allocMode == BUFFER_MANAGER_ALLOCATION_SILENT) {
/* run the allocationThread */
m_allocationThread->run(PRIORITY_DEFAULT);
CLOGI("allocationThread is started");
}
func_exit:
m_flagSkipAllocation = false;
EXYNOS_CAMERA_BUFFER_OUT();
return ret;
}
status_t ExynosCameraBufferManager::m_free(void)
{
EXYNOS_CAMERA_BUFFER_IN();
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
Mutex::Autolock lock(m_lock);
CLOGD("Free the buffer (m_allocatedBufCount=%d) --- dumpBufferInfo ---",
m_allocatedBufCount);
dumpBufferInfo();
status_t ret = NO_ERROR;
if (m_flagAllocated != false) {
if (m_free(m_indexOffset, m_allocatedBufCount + m_indexOffset) != NO_ERROR) {
CLOGE("m_free failed");
ret = INVALID_OPERATION;
goto func_exit;
}
if (m_hasMetaPlane == true) {
if (m_defaultFree(m_indexOffset, m_allocatedBufCount + m_indexOffset, m_hasMetaPlane) != NO_ERROR) {
CLOGE("m_defaultFree failed");
ret = INVALID_OPERATION;
goto func_exit;
}
}
m_availableBufferIndexQLock.lock();
m_availableBufferIndexQ.clear();
m_availableBufferIndexQLock.unlock();
m_allocatedBufCount = 0;
m_allowedMaxBufCount = 0;
m_flagAllocated = false;
}
CLOGD("Free the buffer succeeded (m_allocatedBufCount=%d)",
m_allocatedBufCount);
func_exit:
EXYNOS_CAMERA_BUFFER_OUT();
return ret;
}
void ExynosCameraBufferManager::m_resetSequenceQ()
{
Mutex::Autolock lock(m_availableBufferIndexQLock);
m_availableBufferIndexQ.clear();
for (int bufIndex = m_indexOffset; bufIndex < m_allocatedBufCount + m_indexOffset; bufIndex++)
m_availableBufferIndexQ.push_back(m_buffer[bufIndex].index);
return;
}
void ExynosCameraBufferManager::setContigBufCount(int reservedMemoryCount)
{
CLOGI("reservedMemoryCount(%d)", reservedMemoryCount);
m_reservedMemoryCount = reservedMemoryCount;
return;
}
int ExynosCameraBufferManager::getContigBufCount(void)
{
return m_reservedMemoryCount;
}
/* If Image buffer color format equals YV12, and buffer has MetaDataPlane..
planeCount = 4 (set by user)
size[0] : Image buffer plane Y size
size[1] : Image buffer plane Cr size
size[2] : Image buffer plane Cb size
if (createMetaPlane == true)
size[3] = EXYNOS_CAMERA_META_PLANE_SIZE; (set by BufferManager, internally)
*/
status_t ExynosCameraBufferManager::setInfo(
int planeCount,
unsigned int size[],
unsigned int bytePerLine[],
int reqBufCount,
bool createMetaPlane,
bool needMmap)
{
status_t ret = NO_ERROR;
ret = setInfo(
planeCount,
size,
bytePerLine,
0 /* startBufIndex */,
reqBufCount,
reqBufCount,
1 /* batchSize */,
EXYNOS_CAMERA_BUFFER_ION_NONCACHED_TYPE,
BUFFER_MANAGER_ALLOCATION_ATONCE,
createMetaPlane,
needMmap);
if (ret < 0)
CLOGE("setInfo fail");
return ret;
}
status_t ExynosCameraBufferManager::setInfo(
int planeCount,
unsigned int size[],
unsigned int bytePerLine[],
int reqBufCount,
int allowedMaxBufCount,
exynos_camera_buffer_type_t type,
bool createMetaPlane,
bool needMmap)
{
status_t ret = NO_ERROR;
ret = setInfo(
planeCount,
size,
bytePerLine,
0 /* startBufIndex */,
reqBufCount,
allowedMaxBufCount,
1 /* batchSize */,
type,
BUFFER_MANAGER_ALLOCATION_ONDEMAND,
createMetaPlane,
needMmap);
if (ret < 0)
CLOGE("setInfo fail");
return ret;
}
status_t ExynosCameraBufferManager::setInfo(
int planeCount,
unsigned int size[],
unsigned int bytePerLine[],
int startBufIndex,
int reqBufCount,
bool createMetaPlane,
bool needMmap)
{
status_t ret = NO_ERROR;
ret = setInfo(
planeCount,
size,
bytePerLine,
startBufIndex,
reqBufCount,
reqBufCount,
1 /* batchSize */,
EXYNOS_CAMERA_BUFFER_ION_NONCACHED_TYPE,
BUFFER_MANAGER_ALLOCATION_ATONCE,
createMetaPlane,
needMmap);
if (ret < 0)
CLOGE("setInfo fail");
return ret;
}
status_t ExynosCameraBufferManager::setInfo(
int planeCount,
unsigned int size[],
unsigned int bytePerLine[],
int startBufIndex,
int reqBufCount,
int allowedMaxBufCount,
exynos_camera_buffer_type_t type,
buffer_manager_allocation_mode_t allocMode,
bool createMetaPlane,
bool needMmap)
{
status_t ret = NO_ERROR;
ret = setInfo(
planeCount,
size,
bytePerLine,
startBufIndex,
reqBufCount,
allowedMaxBufCount,
1 /* batchSize */,
type,
allocMode,
createMetaPlane,
needMmap);
if (ret < 0)
ALOGE("ERR(%s[%d]):setInfo fail", __FUNCTION__, __LINE__);
return ret;
}
status_t ExynosCameraBufferManager::setInfo(
int planeCount,
unsigned int size[],
unsigned int bytePerLine[],
int startBufIndex,
int reqBufCount,
int allowedMaxBufCount,
int batchSize,
exynos_camera_buffer_type_t type,
buffer_manager_allocation_mode_t allocMode,
bool createMetaPlane,
bool needMmap)
{
EXYNOS_CAMERA_BUFFER_IN();
Mutex::Autolock lock(m_lock);
status_t ret = NO_ERROR;
int totalPlaneCount = 0;
if (m_indexOffset > 0) {
CLOGD("buffer indexOffset(%d), Index[0 - %d] not used",
m_indexOffset, m_indexOffset);
}
m_indexOffset = startBufIndex;
if (allowedMaxBufCount < reqBufCount) {
CLOGW("abnormal value [reqBufCount=%d, allowedMaxBufCount=%d]",
reqBufCount, allowedMaxBufCount);
allowedMaxBufCount = reqBufCount;
}
if (reqBufCount < 0 || VIDEO_MAX_FRAME < reqBufCount) {
CLOGE("abnormal value [reqBufCount=%d]",
reqBufCount);
ret = BAD_VALUE;
goto func_exit;
}
if (planeCount < 0 || EXYNOS_CAMERA_BUFFER_MAX_PLANES <= planeCount) {
CLOGE("abnormal value [planeCount=%d]",
planeCount);
ret = BAD_VALUE;
goto func_exit;
}
totalPlaneCount = m_getTotalPlaneCount(planeCount, batchSize, createMetaPlane);
if (totalPlaneCount < 1 || EXYNOS_CAMERA_BUFFER_MAX_PLANES < totalPlaneCount) {
CLOGE("Failed to getTotalPlaneCount." \
"totalPlaneCount %d planeCount %d batchSize %d hasMetaPlane %d",
totalPlaneCount, planeCount, batchSize, createMetaPlane);
ret = INVALID_OPERATION;
goto func_exit;
}
if (createMetaPlane == true) {
size[planeCount - 1] = EXYNOS_CAMERA_META_PLANE_SIZE;
m_hasMetaPlane = true;
}
for (int bufIndex = m_indexOffset; bufIndex < allowedMaxBufCount + m_indexOffset; bufIndex++) {
for (int planeIndex = 0; planeIndex < planeCount; planeIndex++) {
if (size[planeIndex] <= 0) {
CLOGE("ERR(%s[%d]):abnormal value [size=%d, planeIndex %d]",
__FUNCTION__, __LINE__, size[planeIndex], planeIndex);
ret = BAD_VALUE;
goto func_exit;
}
int curPlaneIndex = ((createMetaPlane == true && planeIndex == planeCount -1)?
(totalPlaneCount - 1) : planeIndex);
m_buffer[bufIndex].size[curPlaneIndex] = size[planeIndex];
m_buffer[bufIndex].bytesPerLine[curPlaneIndex] = bytePerLine[planeIndex];
}
m_buffer[bufIndex].planeCount = planeCount;
m_buffer[bufIndex].type = type;
m_buffer[bufIndex].batchSize = batchSize;
}
m_allowedMaxBufCount = allowedMaxBufCount + startBufIndex;
m_reqBufCount = reqBufCount;
m_flagNeedMmap = needMmap;
m_allocMode = allocMode;
func_exit:
EXYNOS_CAMERA_BUFFER_OUT();
return ret;
}
status_t ExynosCameraBufferManager::setInfo(
int planeCount,
unsigned int size[],
unsigned int bytePerLine[],
int startBufIndex,
int reqBufCount,
__unused int allowedMaxBufCount,
__unused exynos_camera_buffer_type_t type,
__unused buffer_manager_allocation_mode_t allocMode,
bool createMetaPlane,
int width,
int height,
int stride,
int pixelFormat,
bool needMmap)
{
status_t ret = NO_ERROR;
ret = setInfo(
planeCount,
size,
bytePerLine,
startBufIndex,
reqBufCount,
reqBufCount,
type,
allocMode,
createMetaPlane,
needMmap);
if (ret != NO_ERROR) {
CLOGE("setInfo fail");
return ret;
}
ret = m_graphicBufferAllocator.setSize(width, height, stride);
if (ret != NO_ERROR) {
CLOGE("m_graphicBufferAllocator.setSiz(%d, %d, %d) fail",
width, height, stride);
return ret;
}
ret = m_graphicBufferAllocator.setHalPixelFormat(pixelFormat);
if (ret != NO_ERROR) {
CLOGE("m_graphicBufferAllocator.setHalPixelFormat(%d) fail",
pixelFormat);
return ret;
}
return ret;
}
bool ExynosCameraBufferManager::m_allocationThreadFunc(void)
{
status_t ret = NO_ERROR;
int increaseCount = 1;
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
CLOGI("increase buffer silently - start - "
"(m_allowedMaxBufCount=%d, m_allocatedBufCount=%d, m_reqBufCount=%d)",
m_allowedMaxBufCount, m_allocatedBufCount, m_reqBufCount);
increaseCount = m_allowedMaxBufCount - m_reqBufCount;
/* increase buffer*/
for (int count = 0; count < increaseCount; count++) {
ret = m_increase(1);
if (ret < 0) {
CLOGE("increase the buffer failed");
} else {
m_lock.lock();
m_availableBufferIndexQ.push_back(m_buffer[m_allocatedBufCount + m_indexOffset].index);
m_allocatedBufCount++;
m_lock.unlock();
}
}
dumpBufferInfo();
CLOGI("increase buffer silently - end - (increaseCount=%d)"
"(m_allowedMaxBufCount=%d, m_allocatedBufCount=%d, m_reqBufCount=%d)",
increaseCount,
m_allowedMaxBufCount, m_allocatedBufCount, m_reqBufCount);
/* false : Thread run once */
return false;
}
status_t ExynosCameraBufferManager::registerBuffer(
__unused int frameCount,
__unused buffer_handle_t *handle,
__unused int acquireFence,
__unused int releaseFence,
__unused enum EXYNOS_CAMERA_BUFFER_POSITION position)
{
return NO_ERROR;
}
status_t ExynosCameraBufferManager::putBuffer(
int bufIndex,
enum EXYNOS_CAMERA_BUFFER_POSITION position)
{
EXYNOS_CAMERA_BUFFER_IN();
Mutex::Autolock lock(m_lock);
status_t ret = NO_ERROR;
List<int>::iterator r;
bool found = false;
enum EXYNOS_CAMERA_BUFFER_PERMISSION permission;
int imagePlaneCount = 0;
int batchPlaneIndex = 0;
permission = EXYNOS_CAMERA_BUFFER_PERMISSION_AVAILABLE;
if (bufIndex < 0 || m_allocatedBufCount + m_indexOffset <= bufIndex) {
CLOGE("buffer Index in out of bound [bufIndex=%d], allocatedBufCount(%d)",
bufIndex, m_allocatedBufCount);
ret = INVALID_OPERATION;
goto func_exit;
}
imagePlaneCount = (m_hasMetaPlane == true ? (m_buffer[bufIndex].planeCount - 1)
: m_buffer[bufIndex].planeCount);
batchPlaneIndex = (m_buffer[bufIndex].batchSize - 1) * imagePlaneCount;
if (m_buffer[bufIndex].batchSize > 1
&& m_buffer[bufIndex].fd[0] == m_buffer[bufIndex].fd[batchPlaneIndex]) {
CLOGV("DEBUG(%s[%d]):[B%d]Skip to putBuffer. This buffer is NOT batch buffer",
__FUNCTION__, __LINE__,
bufIndex);
goto func_exit;
}
m_availableBufferIndexQLock.lock();
for (r = m_availableBufferIndexQ.begin(); r != m_availableBufferIndexQ.end(); r++) {
if (bufIndex == *r) {
found = true;
break;
}
}
m_availableBufferIndexQLock.unlock();
if (found == true) {
CLOGV("bufIndex=%d is already in (available state)",
bufIndex);
goto func_exit;
}
if (m_isValidBatchBuffer(bufIndex) == true) {
ret = m_destructBatchBuffer(bufIndex);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):[B%d]Failed to destructBatchBuffer. batchSize %d",
__FUNCTION__, __LINE__,
bufIndex, m_buffer[bufIndex].batchSize);
/* Continue to handle buffer as a single buffer */
}
}
if (m_putBuffer(bufIndex) != NO_ERROR) {
CLOGE("m_putBuffer failed [bufIndex=%d, position=%d, permission=%d]",
bufIndex, (int)position, (int)permission);
ret = INVALID_OPERATION;
goto func_exit;
}
if (updateStatus(bufIndex, 0, position, permission) != NO_ERROR) {
CLOGE("setStatus failed [bufIndex=%d, position=%d, permission=%d]",
bufIndex, (int)position, (int)permission);
ret = INVALID_OPERATION;
goto func_exit;
}
m_availableBufferIndexQLock.lock();
m_availableBufferIndexQ.push_back(m_buffer[bufIndex].index);
m_availableBufferIndexQLock.unlock();
func_exit:
EXYNOS_CAMERA_BUFFER_OUT();
return ret;
}
/* User Process need to check the index of buffer returned from "getBuffer()" */
status_t ExynosCameraBufferManager::getBuffer(
int *reqBufIndex,
enum EXYNOS_CAMERA_BUFFER_POSITION position,
struct ExynosCameraBuffer *buffer)
{
EXYNOS_CAMERA_BUFFER_IN();
Mutex::Autolock lock(m_lock);
status_t ret = NO_ERROR;
List<int>::iterator r;
int bufferIndex;
enum EXYNOS_CAMERA_BUFFER_PERMISSION permission;
int acquireFence = -1;
int releaseFence = -1;
bufferIndex = *reqBufIndex;
permission = EXYNOS_CAMERA_BUFFER_PERMISSION_NONE;
if (m_allocatedBufCount == 0) {
CLOGE("m_allocatedBufCount equals zero");
ret = INVALID_OPERATION;
goto func_exit;
}
if (m_getBuffer(&bufferIndex, &acquireFence, &releaseFence) != NO_ERROR) {
CLOGE("m_getBuffer failed [bufferIndex=%d, position=%d, permission=%d]",
bufferIndex, (int)position, (int)permission);
ret = INVALID_OPERATION;
goto func_exit;
}
reDo:
if (bufferIndex < 0 || m_allocatedBufCount + m_indexOffset <= bufferIndex) {
/* find availableBuffer */
m_availableBufferIndexQLock.lock();
if (m_availableBufferIndexQ.empty() == false) {
r = m_availableBufferIndexQ.begin();
bufferIndex = *r;
m_availableBufferIndexQ.erase(r);
#ifdef EXYNOS_CAMERA_BUFFER_TRACE
CLOGI("available buffer [index=%d]...",
bufferIndex);
#endif
}
m_availableBufferIndexQLock.unlock();
} else {
m_availableBufferIndexQLock.lock();
/* get the Buffer of requested */
for (r = m_availableBufferIndexQ.begin(); r != m_availableBufferIndexQ.end(); r++) {
if (bufferIndex == *r) {
m_availableBufferIndexQ.erase(r);
break;
}
}
m_availableBufferIndexQLock.unlock();
}
if (0 <= bufferIndex && bufferIndex < m_allocatedBufCount + m_indexOffset) {
/* found buffer */
if (isAvaliable(bufferIndex) == false) {
CLOGE("isAvaliable failed [bufferIndex=%d]",
bufferIndex);
ret = BAD_VALUE;
goto func_exit;
}
permission = EXYNOS_CAMERA_BUFFER_PERMISSION_IN_PROCESS;
if (updateStatus(bufferIndex, 0, position, permission) != NO_ERROR) {
CLOGE("setStatus failed [bIndex=%d, position=%d, permission=%d]",
bufferIndex, (int)position, (int)permission);
ret = INVALID_OPERATION;
goto func_exit;
}
} else {
/* do not find buffer */
if (m_allocMode == BUFFER_MANAGER_ALLOCATION_ONDEMAND) {
/* increase buffer*/
ret = m_increase(1);
if (ret < 0) {
CLOGE("increase the buffer failed, m_allocatedBufCount %d, bufferIndex %d",
m_allocatedBufCount, bufferIndex);
} else {
m_availableBufferIndexQLock.lock();
m_availableBufferIndexQ.push_back(m_allocatedBufCount + m_indexOffset);
m_availableBufferIndexQLock.unlock();
bufferIndex = m_allocatedBufCount + m_indexOffset;
m_allocatedBufCount++;
dumpBufferInfo();
CLOGI("increase the buffer succeeded (bufferIndex=%d)",
bufferIndex);
goto reDo;
}
} else {
if (m_allocatedBufCount == 1)
bufferIndex = 0;
else
ret = INVALID_OPERATION;
}
if (ret < 0) {
#ifdef EXYNOS_CAMERA_BUFFER_TRACE
CLOGD("find free buffer... failed --- dump ---");
dump();
CLOGD("----------------------------------------");
CLOGD("buffer Index in out of bound [bufferIndex=%d]",
bufferIndex);
#endif
ret = BAD_VALUE;
goto func_exit;
}
}
m_buffer[bufferIndex].index = bufferIndex;
m_buffer[bufferIndex].acquireFence = acquireFence;
m_buffer[bufferIndex].releaseFence = releaseFence;
if (m_buffer[bufferIndex].batchSize > 1) {
ret = m_constructBatchBuffer(bufferIndex);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):[I%d]Failed to constructBatchBuffer. batchSize %d",
__FUNCTION__, __LINE__,
bufferIndex, m_buffer[bufferIndex].batchSize);
m_lock.unlock();
#ifdef USE_GRALLOC_REUSE_SUPPORT
ret = cancelBuffer(bufferIndex, true);
#else
ret = cancelBuffer(bufferIndex);
#endif
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):[I%d]Failed to cancelBuffer",
__FUNCTION__, __LINE__,
bufferIndex);
}
ret = INVALID_OPERATION;
goto func_exit;
}
}
*reqBufIndex = bufferIndex;
*buffer = m_buffer[bufferIndex];
func_exit:
EXYNOS_CAMERA_BUFFER_OUT();
return ret;
}
status_t ExynosCameraBufferManager::increase(int increaseCount)
{
CLOGD("increaseCount(%d) function invalid. Do nothing", increaseCount);
return NO_ERROR;
}
#ifdef USE_GRALLOC_REUSE_SUPPORT
status_t ExynosCameraBufferManager::cancelBuffer(int bufIndex, bool isReuse)
#else
status_t ExynosCameraBufferManager::cancelBuffer(int bufIndex)
#endif
{
int ret = NO_ERROR;
#ifdef USE_GRALLOC_REUSE_SUPPORT
if (isReuse == true) {
CLOGD("cancelBuffer bufIndex(%d) isReuse(true) function invalid, put buffer", bufIndex);
}
#endif
{
ret = putBuffer(bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_NONE);
}
return ret;
}
int ExynosCameraBufferManager::getBufStride(void)
{
return 0;
}
status_t ExynosCameraBufferManager::updateStatus(
int bufIndex,
int driverValue,
enum EXYNOS_CAMERA_BUFFER_POSITION position,
enum EXYNOS_CAMERA_BUFFER_PERMISSION permission)
{
if (bufIndex < 0) {
CLOGE("Invalid buffer index %d", bufIndex);
return BAD_VALUE;
}
m_buffer[bufIndex].index = bufIndex;
m_buffer[bufIndex].status.driverReturnValue = driverValue;
m_buffer[bufIndex].status.position = position;
m_buffer[bufIndex].status.permission = permission;
return NO_ERROR;
}
status_t ExynosCameraBufferManager::getStatus(
int bufIndex,
struct ExynosCameraBufferStatus *bufStatus)
{
*bufStatus = m_buffer[bufIndex].status;
return NO_ERROR;
}
status_t ExynosCameraBufferManager::getIndexByHandle(__unused buffer_handle_t *handle, __unused int *index)
{
return NO_ERROR;
}
status_t ExynosCameraBufferManager::getHandleByIndex(__unused buffer_handle_t **handle, __unused int index)
{
return NO_ERROR;
}
sp<GraphicBuffer> ExynosCameraBufferManager::getGraphicBuffer(int index)
{
EXYNOS_CAMERA_BUFFER_IN();
sp<GraphicBuffer> graphicBuffer;
int planeCount = 0;
if ((index < 0) || (index >= m_allowedMaxBufCount)) {
CLOGE("Buffer index error (%d/%d)", index, m_allowedMaxBufCount);
goto done;
}
planeCount = m_buffer[index].planeCount;
if (m_hasMetaPlane == true) {
planeCount--;
}
graphicBuffer = m_graphicBufferAllocator.alloc(index, planeCount, m_buffer[index].fd, m_buffer[index].addr, m_buffer[index].size);
if (graphicBuffer == 0) {
CLOGE("m_graphicBufferAllocator.alloc(%d) fail", index);
goto done;
}
done:
EXYNOS_CAMERA_BUFFER_OUT();
return graphicBuffer;
}
status_t ExynosCameraBufferManager::getIndexByFd(int fd, int *index)
{
status_t ret = NO_ERROR;
if (fd < 0) {
CLOGE("Invalid FD %d",
fd);
return BAD_VALUE;
}
*index = -1;
for (int bufIndex = m_indexOffset; bufIndex < m_reqBufCount + m_indexOffset; bufIndex++) {
int imagePlaneCount = (m_hasMetaPlane == true ? (m_buffer[bufIndex].planeCount - 1)
: m_buffer[bufIndex].planeCount);
int batchPlaneIndex = (m_buffer[bufIndex].batchSize - 1) * imagePlaneCount;
if (m_buffer[bufIndex].fd[batchPlaneIndex] == fd) {
*index = bufIndex;
break;
}
}
if (*index < 0 || *index > m_allowedMaxBufCount + m_indexOffset) {
CLOGE("Invalid buffer index %d. fd %d",
*index, fd);
*index = -1;
return INVALID_OPERATION;
}
return NO_ERROR;
}
bool ExynosCameraBufferManager::isAllocated(void)
{
return m_flagAllocated;
}
bool ExynosCameraBufferManager::isAvaliable(int bufIndex)
{
bool ret = false;
if (bufIndex < 0) {
CLOGE("invalid bufIndex(%d)", bufIndex);
dump();
return false;
}
switch (m_buffer[bufIndex].status.permission) {
case EXYNOS_CAMERA_BUFFER_PERMISSION_NONE:
case EXYNOS_CAMERA_BUFFER_PERMISSION_AVAILABLE:
ret = true;
break;
case EXYNOS_CAMERA_BUFFER_PERMISSION_IN_PROCESS:
default:
#ifdef EXYNOS_CAMERA_BUFFER_TRACE
CLOGD("buffer is not available");
dump();
#endif
ret = false;
break;
}
return ret;
}
status_t ExynosCameraBufferManager::m_setDefaultAllocator(void *allocator)
{
m_defaultAllocator = (ExynosCameraIonAllocator *)allocator;
return NO_ERROR;
}
status_t ExynosCameraBufferManager::m_defaultAlloc(int bIndex, int eIndex, bool isMetaPlane)
{
EXYNOS_CAMERA_BUFFER_IN();
status_t ret = NO_ERROR;
int planeIndexStart = 0;
int planeIndexEnd = 0;
bool mapNeeded = false;
#ifdef DEBUG_RAWDUMP
char enableRawDump[PROP_VALUE_MAX];
#endif /* DEBUG_RAWDUMP */
int mask = EXYNOS_CAMERA_BUFFER_ION_MASK_NONCACHED;
int flags = EXYNOS_CAMERA_BUFFER_ION_FLAG_NONCACHED;
ExynosCameraDurationTimer m_timer;
long long durationTime = 0;
long long durationTimeSum = 0;
unsigned int estimatedBase = EXYNOS_CAMERA_BUFFER_ION_WARNING_TIME_NONCACHED;
unsigned int estimatedTime = 0;
unsigned int bufferSize = 0;
int reservedMaxCount = 0;
int bufIndex = 0;
if (m_defaultAllocator == NULL) {
CLOGE("m_defaultAllocator equals NULL");
ret = INVALID_OPERATION;
goto func_exit;
}
if (bIndex < 0 || eIndex < 0) {
CLOGE("Invalid index parameters. bIndex %d eIndex %d",
bIndex, eIndex);
ret = BAD_VALUE;
goto func_exit;
}
if (isMetaPlane == true) {
mapNeeded = true;
} else {
#ifdef DEBUG_RAWDUMP
mapNeeded = true;
#else
mapNeeded = m_flagNeedMmap;
#endif
}
for (bufIndex = bIndex; bufIndex < eIndex; bufIndex++) {
if (isMetaPlane == true) {
planeIndexStart = m_buffer[bufIndex].getMetaPlaneIndex();
planeIndexEnd = planeIndexStart + 1;
mask = EXYNOS_CAMERA_BUFFER_ION_MASK_NONCACHED;
flags = EXYNOS_CAMERA_BUFFER_ION_FLAG_NONCACHED;
estimatedBase = EXYNOS_CAMERA_BUFFER_ION_WARNING_TIME_NONCACHED;
} else {
planeIndexStart = 0;
planeIndexEnd = (m_hasMetaPlane ? m_buffer[bufIndex].planeCount-1
: m_buffer[bufIndex].planeCount);
switch (m_buffer[bufIndex].type) {
case EXYNOS_CAMERA_BUFFER_ION_NONCACHED_TYPE:
mask = EXYNOS_CAMERA_BUFFER_ION_MASK_NONCACHED;
flags = EXYNOS_CAMERA_BUFFER_ION_FLAG_NONCACHED;
estimatedBase = EXYNOS_CAMERA_BUFFER_ION_WARNING_TIME_NONCACHED;
break;
case EXYNOS_CAMERA_BUFFER_ION_CACHED_TYPE:
mask = EXYNOS_CAMERA_BUFFER_ION_MASK_CACHED;
flags = EXYNOS_CAMERA_BUFFER_ION_FLAG_CACHED;
estimatedBase = EXYNOS_CAMERA_BUFFER_ION_WARNING_TIME_CACHED;
break;
case EXYNOS_CAMERA_BUFFER_ION_RESERVED_TYPE:
/* case EXYNOS_CAMERA_BUFFER_ION_NONCACHED_RESERVED_TYPE: */
#ifdef RESERVED_MEMORY_ENABLE
reservedMaxCount = (m_reservedMemoryCount > 0 ? m_reservedMemoryCount : RESERVED_BUFFER_COUNT_MAX);
#else
reservedMaxCount = 0;
#endif
if (bufIndex < reservedMaxCount) {
CLOGI("bufIndex(%d) < reservedMaxCount(%d) , m_reservedMemoryCount(%d), non-cached",
bufIndex, reservedMaxCount, m_reservedMemoryCount);
mask = EXYNOS_CAMERA_BUFFER_ION_MASK_RESERVED;
flags = EXYNOS_CAMERA_BUFFER_ION_FLAG_RESERVED;
estimatedBase = EXYNOS_CAMERA_BUFFER_ION_WARNING_TIME_RESERVED;
} else {
CLOGI("bufIndex(%d) >= reservedMaxCount(%d) , m_reservedMemoryCount(%d),"
"non-cached. so, alloc ion memory instead of reserved memory",
bufIndex, reservedMaxCount, m_reservedMemoryCount);
mask = EXYNOS_CAMERA_BUFFER_ION_MASK_NONCACHED;
flags = EXYNOS_CAMERA_BUFFER_ION_FLAG_NONCACHED;
estimatedBase = EXYNOS_CAMERA_BUFFER_ION_WARNING_TIME_NONCACHED;
}
break;
case EXYNOS_CAMERA_BUFFER_ION_CACHED_RESERVED_TYPE:
#ifdef RESERVED_MEMORY_ENABLE
reservedMaxCount = (m_reservedMemoryCount > 0 ? m_reservedMemoryCount : RESERVED_BUFFER_COUNT_MAX);
#else
reservedMaxCount = 0;
#endif
if (bufIndex < reservedMaxCount) {
CLOGI("bufIndex(%d) < reservedMaxCount(%d) , m_reservedMemoryCount(%d), cached",
bufIndex, reservedMaxCount, m_reservedMemoryCount);
mask = EXYNOS_CAMERA_BUFFER_ION_MASK_RESERVED;
flags = EXYNOS_CAMERA_BUFFER_ION_FLAG_RESERVED | EXYNOS_CAMERA_BUFFER_ION_FLAG_CACHED;
estimatedBase = EXYNOS_CAMERA_BUFFER_ION_WARNING_TIME_RESERVED;
} else {
CLOGI("bufIndex(%d) >= reservedMaxCount(%d) , m_reservedMemoryCount(%d),"
"cached. so, alloc ion memory instead of reserved memory",
bufIndex, reservedMaxCount, m_reservedMemoryCount);
mask = EXYNOS_CAMERA_BUFFER_ION_MASK_CACHED;
flags = EXYNOS_CAMERA_BUFFER_ION_FLAG_CACHED_SYNC_FORCE;
estimatedBase = EXYNOS_CAMERA_BUFFER_ION_WARNING_TIME_CACHED;
}
break;
case EXYNOS_CAMERA_BUFFER_ION_CACHED_SYNC_FORCE_TYPE:
ALOGD("SYNC_FORCE_CACHED");
mask = EXYNOS_CAMERA_BUFFER_ION_MASK_CACHED;
flags = EXYNOS_CAMERA_BUFFER_ION_FLAG_CACHED_SYNC_FORCE;
estimatedBase = EXYNOS_CAMERA_BUFFER_ION_WARNING_TIME_CACHED;
break;
case EXYNOS_CAMERA_BUFFER_ION_RESERVED_SECURE_TYPE:
#ifdef RESERVED_MEMORY_ENABLE
reservedMaxCount = (m_reservedMemoryCount > 0 ? m_reservedMemoryCount : RESERVED_BUFFER_COUNT_MAX);
#else
reservedMaxCount = 0;
#endif
if (bufIndex < reservedMaxCount) {
CLOGI("bufIndex(%d) < reservedMaxCount(%d) , m_reservedMemoryCount(%d), non-cached",
bufIndex, reservedMaxCount, m_reservedMemoryCount);
mask = EXYNOS_CAMERA_BUFFER_ION_MASK_SECURE;
flags = EXYNOS_CAMERA_BUFFER_ION_FLAG_SECURE;
estimatedBase = EXYNOS_CAMERA_BUFFER_ION_WARNING_TIME_RESERVED;
} else {
CLOGI("bufIndex(%d) >= reservedMaxCount(%d) , m_reservedMemoryCount(%d),"
"non-cached. so, alloc ion memory instead of reserved memory",
bufIndex, reservedMaxCount, m_reservedMemoryCount);
mask = EXYNOS_CAMERA_BUFFER_ION_MASK_NONCACHED;
flags = EXYNOS_CAMERA_BUFFER_ION_MASK_NONCACHED;
estimatedBase = EXYNOS_CAMERA_BUFFER_ION_WARNING_TIME_NONCACHED;
}
break;
case EXYNOS_CAMERA_BUFFER_ION_CACHED_RESERVED_SECURE_TYPE:
#ifdef RESERVED_MEMORY_ENABLE
reservedMaxCount = (m_reservedMemoryCount > 0 ? m_reservedMemoryCount : RESERVED_BUFFER_COUNT_MAX);
#else
reservedMaxCount = 0;
#endif
if (bufIndex < reservedMaxCount) {
CLOGI("bufIndex(%d) < reservedMaxCount(%d) , m_reservedMemoryCount(%d), cached",
bufIndex, reservedMaxCount, m_reservedMemoryCount);
mask = EXYNOS_CAMERA_BUFFER_ION_MASK_SECURE;
flags = EXYNOS_CAMERA_BUFFER_ION_FLAG_SECURE | EXYNOS_CAMERA_BUFFER_ION_FLAG_CACHED;
estimatedBase = EXYNOS_CAMERA_BUFFER_ION_WARNING_TIME_RESERVED;
} else {
CLOGI("bufIndex(%d) >= reservedMaxCount(%d) , m_reservedMemoryCount(%d),"
"cached. so, alloc ion memory instead of reserved memory",
bufIndex, reservedMaxCount, m_reservedMemoryCount);
mask = EXYNOS_CAMERA_BUFFER_ION_MASK_CACHED;
flags = EXYNOS_CAMERA_BUFFER_ION_FLAG_CACHED;
estimatedBase = EXYNOS_CAMERA_BUFFER_ION_WARNING_TIME_CACHED;
}
break;
case EXYNOS_CAMERA_BUFFER_INVALID_TYPE:
default:
CLOGE("buffer type is invaild (%d)", (int)m_buffer[bufIndex].type);
break;
}
}
if (isMetaPlane == false) {
m_timer.start();
bufferSize = 0;
}
for (int planeIndex = planeIndexStart; planeIndex < planeIndexEnd; planeIndex++) {
if (m_buffer[bufIndex].fd[planeIndex] >= 0) {
CLOGE("buffer[%d].fd[%d] = %d already allocated",
bufIndex, planeIndex, m_buffer[bufIndex].fd[planeIndex]);
continue;
}
if (m_defaultAllocator->alloc(
m_buffer[bufIndex].size[planeIndex],
&(m_buffer[bufIndex].fd[planeIndex]),
&(m_buffer[bufIndex].addr[planeIndex]),
mask,
flags,
mapNeeded) != NO_ERROR) {
#if defined(RESERVED_MEMORY_ENABLE) && defined(RESERVED_MEMORY_REALLOC_WITH_ION)
if (m_buffer[bufIndex].type == EXYNOS_CAMERA_BUFFER_ION_RESERVED_TYPE) {
CLOGE("Realloc with ion:bufIndex(%d), m_reservedMemoryCount(%d),"
" non-cached. so, alloc ion memory instead of reserved memory",
bufIndex, m_reservedMemoryCount);
mask = EXYNOS_CAMERA_BUFFER_ION_MASK_NONCACHED;
flags = EXYNOS_CAMERA_BUFFER_ION_FLAG_NONCACHED;
estimatedBase = EXYNOS_CAMERA_BUFFER_ION_WARNING_TIME_NONCACHED;
} else if (m_buffer[bufIndex].type == EXYNOS_CAMERA_BUFFER_ION_CACHED_RESERVED_TYPE) {
CLOGE("Realloc with ion:bufIndex(%d), m_reservedMemoryCount(%d),"
" cached. so, alloc ion memory instead of reserved memory",
bufIndex, m_reservedMemoryCount);
mask = EXYNOS_CAMERA_BUFFER_ION_MASK_CACHED;
flags = EXYNOS_CAMERA_BUFFER_ION_FLAG_CACHED_SYNC_FORCE;
estimatedBase = EXYNOS_CAMERA_BUFFER_ION_WARNING_TIME_CACHED;
} else {
CLOGE("m_defaultAllocator->alloc(bufIndex=%d, planeIndex=%d, size=%d) failed",
bufIndex, planeIndex, m_buffer[bufIndex].size[planeIndex]);
ret = INVALID_OPERATION;
goto func_exit;
}
if (m_defaultAllocator->alloc(
m_buffer[bufIndex].size[planeIndex],
&(m_buffer[bufIndex].fd[planeIndex]),
&(m_buffer[bufIndex].addr[planeIndex]),
mask,
flags,
mapNeeded) != NO_ERROR) {
CLOGE("m_defaultAllocator->alloc(bufIndex=%d, planeIndex=%d, size=%d) failed",
bufIndex, planeIndex, m_buffer[bufIndex].size[planeIndex]);
ret = INVALID_OPERATION;
goto func_exit;
}
#else
CLOGE("m_defaultAllocator->alloc(bufIndex=%d, planeIndex=%d, size=%d) failed",
bufIndex, planeIndex, m_buffer[bufIndex].size[planeIndex]);
ret = INVALID_OPERATION;
goto func_exit;
#endif
}
#ifdef EXYNOS_CAMERA_BUFFER_TRACE
printBufferInfo(__FUNCTION__, __LINE__, bufIndex, planeIndex);
#endif
if (isMetaPlane == false) {
bufferSize = bufferSize + m_buffer[bufIndex].size[planeIndex];
/* Mirroring original plane to last plane */
if (m_buffer[bufIndex].batchSize > 1) {
int imagePlaneCount = (m_hasMetaPlane == true ? (m_buffer[bufIndex].planeCount - 1)
: m_buffer[bufIndex].planeCount);
int batchPlaneIndex = (m_buffer[bufIndex].batchSize - 1) * imagePlaneCount + planeIndex;
m_buffer[bufIndex].size[batchPlaneIndex] = m_buffer[bufIndex].size[planeIndex];
m_buffer[bufIndex].bytesPerLine[batchPlaneIndex] = m_buffer[bufIndex].bytesPerLine[planeIndex];
m_buffer[bufIndex].fd[batchPlaneIndex] = m_buffer[bufIndex].fd[planeIndex];
m_buffer[bufIndex].addr[batchPlaneIndex] = m_buffer[bufIndex].addr[planeIndex];
}
}
}
if (isMetaPlane == false) {
m_timer.stop();
durationTime = m_timer.durationMsecs();
durationTimeSum += durationTime;
#ifdef EXYNOS_CAMERA_BUFFER_TRACE
CLOGD("duration time(%5d msec):(type=%d, bufIndex=%d, size=%.2f)",
(int)durationTime, m_buffer[bufIndex].type, bufIndex, (float)bufferSize / (float)(1024 * 1024));
#endif
estimatedTime = estimatedBase * bufferSize / EXYNOS_CAMERA_BUFFER_1MB;
if (estimatedTime < durationTime) {
CLOGW("estimated time(%5d msec):(type=%d, bufIndex=%d, size=%d)",
(int)estimatedTime, m_buffer[bufIndex].type, bufIndex, (int)bufferSize);
}
}
if (updateStatus(
bufIndex,
0,
EXYNOS_CAMERA_BUFFER_POSITION_NONE,
EXYNOS_CAMERA_BUFFER_PERMISSION_AVAILABLE) != NO_ERROR) {
CLOGE("setStatus failed [bIndex=%d, position=NONE, permission=NONE]",
bufIndex);
ret = INVALID_OPERATION;
goto func_exit;
}
}
if ((planeIndexEnd - planeIndexStart) == 1) {
CLOGD("Duration time of buffer(Plane:%d) allocation(%5d msec)", planeIndexStart, (int)durationTimeSum);
} else if ((planeIndexEnd - planeIndexStart) > 1) {
CLOGD("Duration time of buffer(Plane:%d~%d) allocation(%5d msec)",planeIndexStart, (planeIndexEnd - 1), (int)durationTimeSum);
}
EXYNOS_CAMERA_BUFFER_OUT();
return ret;
func_exit:
EXYNOS_CAMERA_BUFFER_OUT();
if (bufIndex < eIndex) {
if (m_defaultFree(0, bufIndex, isMetaPlane) != NO_ERROR) {
CLOGE("m_defaultFree failed");
}
}
return ret;
}
status_t ExynosCameraBufferManager::m_defaultFree(int bIndex, int eIndex, bool isMetaPlane)
{
EXYNOS_CAMERA_BUFFER_IN();
status_t ret = NO_ERROR;
int planeIndexStart = 0;
int planeIndexEnd = 0;
bool mapNeeded = false;
#ifdef DEBUG_RAWDUMP
char enableRawDump[PROP_VALUE_MAX];
#endif /* DEBUG_RAWDUMP */
if (isMetaPlane == true) {
mapNeeded = true;
} else {
#ifdef DEBUG_RAWDUMP
mapNeeded = true;
#else
mapNeeded = m_flagNeedMmap;
#endif
}
for (int bufIndex = bIndex; bufIndex < eIndex; bufIndex++) {
if (isAvaliable(bufIndex) == false) {
CLOGE("buffer [bufIndex=%d] in InProcess state",
bufIndex);
if (m_isDestructor == false) {
ret = BAD_VALUE;
continue;
} else {
CLOGE("buffer [bufIndex=%d] in InProcess state, but try to forcedly free",
bufIndex);
}
}
if (isMetaPlane == true) {
planeIndexStart = m_buffer[bufIndex].getMetaPlaneIndex();
planeIndexEnd = planeIndexStart + 1;
} else {
planeIndexStart = 0;
planeIndexEnd = (m_hasMetaPlane ? m_buffer[bufIndex].planeCount-1
: m_buffer[bufIndex].planeCount);
}
for (int planeIndex = planeIndexStart; planeIndex < planeIndexEnd; planeIndex++) {
if (m_defaultAllocator->free(
m_buffer[bufIndex].size[planeIndex],
&(m_buffer[bufIndex].fd[planeIndex]),
&(m_buffer[bufIndex].addr[planeIndex]),
mapNeeded) != NO_ERROR) {
CLOGE("m_defaultAllocator->free for Imagedata Plane failed." \
"bufIndex %d planeIndex %d fd %d addr %p",
bufIndex, planeIndex,
m_buffer[bufIndex].fd[planeIndex],
m_buffer[bufIndex].addr[planeIndex]);
ret = INVALID_OPERATION;
goto func_exit;
}
/* Clear the mirrored last plane */
if (isMetaPlane == false && m_buffer[bufIndex].batchSize > 1) {
int imagePlaneCount = (m_hasMetaPlane == true ? (m_buffer[bufIndex].planeCount - 1)
: m_buffer[bufIndex].planeCount);
int batchPlaneIndex = (m_buffer[bufIndex].batchSize - 1) * imagePlaneCount + planeIndex;
m_buffer[bufIndex].size[batchPlaneIndex] = 0;
m_buffer[bufIndex].bytesPerLine[batchPlaneIndex] = 0;
m_buffer[bufIndex].fd[batchPlaneIndex] = -1;
m_buffer[bufIndex].addr[batchPlaneIndex] = 0;
}
}
if (updateStatus(
bufIndex,
0,
EXYNOS_CAMERA_BUFFER_POSITION_NONE,
EXYNOS_CAMERA_BUFFER_PERMISSION_NONE) != NO_ERROR) {
CLOGE("setStatus failed [bIndex=%d, position=NONE, permission=NONE]",
bufIndex);
ret = INVALID_OPERATION;
goto func_exit;
}
if (m_graphicBufferAllocator.free(bufIndex) != NO_ERROR) {
CLOGE("m_graphicBufferAllocator.free(%d) fail",
bufIndex);
ret = INVALID_OPERATION;
goto func_exit;
}
}
func_exit:
EXYNOS_CAMERA_BUFFER_OUT();
return ret;
}
bool ExynosCameraBufferManager::m_checkInfoForAlloc(void)
{
EXYNOS_CAMERA_BUFFER_IN();
bool ret = true;
if (m_reqBufCount < 0 || VIDEO_MAX_FRAME < m_reqBufCount) {
CLOGE("buffer Count in out of bound [m_reqBufCount=%d]",
m_reqBufCount);
ret = false;
goto func_exit;
}
for (int bufIndex = m_indexOffset; bufIndex < m_reqBufCount + m_indexOffset; bufIndex++) {
if (m_buffer[bufIndex].planeCount < 0
|| VIDEO_MAX_PLANES <= m_buffer[bufIndex].planeCount) {
CLOGE("plane Count in out of bound [m_buffer[bIndex].planeCount=%d]",
m_buffer[bufIndex].planeCount);
ret = false;
goto func_exit;
}
for (int planeIndex = 0; planeIndex < m_buffer[bufIndex].planeCount; planeIndex++) {
int curPlaneIndex = ((m_hasMetaPlane == true
&& planeIndex == m_buffer[bufIndex].planeCount -1) ?
m_buffer[bufIndex].getMetaPlaneIndex() : planeIndex);
if (m_buffer[bufIndex].size[curPlaneIndex] == 0) {
CLOGE("size is empty [m_buffer[%d].size[%d]=%d]",
bufIndex, curPlaneIndex, m_buffer[bufIndex].size[curPlaneIndex]);
ret = false;
goto func_exit;
}
}
}
func_exit:
EXYNOS_CAMERA_BUFFER_OUT();
return ret;
}
status_t ExynosCameraBufferManager::m_createDefaultAllocator(bool isCached)
{
EXYNOS_CAMERA_BUFFER_IN();
status_t ret = NO_ERROR;
m_defaultAllocator = new ExynosCameraIonAllocator();
m_isCreateDefaultAllocator = true;
if (m_defaultAllocator->init(isCached) != NO_ERROR) {
CLOGE("m_defaultAllocator->init failed");
ret = INVALID_OPERATION;
goto func_exit;
}
func_exit:
EXYNOS_CAMERA_BUFFER_OUT();
return ret;
}
int ExynosCameraBufferManager::m_getTotalPlaneCount(int planeCount, int batchSize, bool hasMetaPlane)
{
if (planeCount < 1 || batchSize < 1) {
CLOGE("ERR(%s[%d]):Invalid values. planeCount %d batchSize %d",
__FUNCTION__, __LINE__,
planeCount, batchSize);
return 0;
}
int totalPlaneCount = 0;
if (hasMetaPlane == true) {
int imagePlaneCount = planeCount - 1;
totalPlaneCount = (imagePlaneCount * batchSize) + 1;
} else {
totalPlaneCount = planeCount * batchSize;
}
return totalPlaneCount;
}
status_t ExynosCameraBufferManager::m_constructBatchBuffer(int bufIndex)
{
status_t ret = NO_ERROR;
if (getNumOfAvailableBuffer() < m_buffer[bufIndex].batchSize - 1) {
CLOGW("NOT enough buffer for constructBatchBuffer.\
batchSize %d availableBuffer %d",
m_buffer[bufIndex].batchSize,
getNumOfAvailableBuffer());
return INVALID_OPERATION;
}
/* Move original image plane to last image plane */
int imagePlaneCount = (m_hasMetaPlane == true ? (m_buffer[bufIndex].planeCount - 1)
: m_buffer[bufIndex].planeCount);
int batchPlaneIndex = 0;
for (int planeIndex = 0; planeIndex < imagePlaneCount; planeIndex++) {
batchPlaneIndex = (m_buffer[bufIndex].batchSize - 1) * imagePlaneCount + planeIndex;
m_buffer[bufIndex].size[batchPlaneIndex] = m_buffer[bufIndex].size[planeIndex];
m_buffer[bufIndex].bytesPerLine[batchPlaneIndex] = m_buffer[bufIndex].bytesPerLine[planeIndex];
m_buffer[bufIndex].fd[batchPlaneIndex] = m_buffer[bufIndex].fd[planeIndex];
m_buffer[bufIndex].addr[batchPlaneIndex] = m_buffer[bufIndex].addr[planeIndex];
}
for (int batchIndex = 0; batchIndex < m_buffer[bufIndex].batchSize - 1; batchIndex++) {
int srcBufferIndex = -1;
/* Find available buffer */
m_availableBufferIndexQLock.lock();
if (m_availableBufferIndexQ.empty() == false) {
List<int>::iterator r = m_availableBufferIndexQ.begin();
srcBufferIndex = *r;
m_availableBufferIndexQ.erase(r);
}
m_availableBufferIndexQLock.unlock();
/* Check buffer validation */
if (isAvaliable(srcBufferIndex) == false) {
CLOGE("[B%d]isAvailable failed",
srcBufferIndex);
return INVALID_OPERATION;
}
/* Update buffer status */
enum EXYNOS_CAMERA_BUFFER_POSITION position = EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL;
enum EXYNOS_CAMERA_BUFFER_PERMISSION permission = EXYNOS_CAMERA_BUFFER_PERMISSION_IN_PROCESS;
ret = updateStatus(srcBufferIndex, 0, position, permission);
if (ret != NO_ERROR) {
CLOGE("[B%d]Failed to updateStatus. position %d, permission %d",
srcBufferIndex, position, permission);
return ret;
}
CLOGV("[B%d]SrcBufferIndex %d BatchIndex %d Available %d",
bufIndex,
srcBufferIndex, batchIndex,
getNumOfAvailableBuffer());
/* Move plane information into batch buffer */
for (int planeIndex = 0; planeIndex < imagePlaneCount; planeIndex++) {
batchPlaneIndex = batchIndex * imagePlaneCount + planeIndex;
m_buffer[bufIndex].size[batchPlaneIndex] = m_buffer[srcBufferIndex].size[planeIndex];
m_buffer[bufIndex].bytesPerLine[batchPlaneIndex] = m_buffer[srcBufferIndex].bytesPerLine[planeIndex];
m_buffer[bufIndex].fd[batchPlaneIndex] = m_buffer[srcBufferIndex].fd[planeIndex];
m_buffer[bufIndex].addr[batchPlaneIndex] = m_buffer[srcBufferIndex].addr[planeIndex];
}
}
return ret;
}
status_t ExynosCameraBufferManager::m_destructBatchBuffer(int bufIndex)
{
status_t ret = NO_ERROR;
int imagePlaneCount = (m_hasMetaPlane == true ? (m_buffer[bufIndex].planeCount - 1)
: m_buffer[bufIndex].planeCount);
int batchPlaneIndex = 0;
for (int batchIndex = 0; batchIndex < m_buffer[bufIndex].batchSize - 1; batchIndex++) {
int dstBufferIndex = -1;
/* Find buffer index by fd */
batchPlaneIndex = batchIndex * imagePlaneCount;
ret = getIndexByFd(m_buffer[bufIndex].fd[batchPlaneIndex], &dstBufferIndex);
if (ret != NO_ERROR
|| dstBufferIndex < 0
|| m_allocatedBufCount + m_indexOffset <= dstBufferIndex) {
CLOGE("[B%d]Failed to getIndexByFd %d, dstBufferIndex %d, batchIndex %d, batchSize %d",
bufIndex,
m_buffer[bufIndex].fd[batchPlaneIndex],
dstBufferIndex,
batchPlaneIndex,
m_buffer[bufIndex].batchSize);
/* Continue to handle the remained planes */
continue;
}
CLOGV("[B%d]DstBufferIndex %d BatchIndex %d available %d",
bufIndex,
dstBufferIndex, batchIndex,
getNumOfAvailableBuffer());
/* Clear batch buffer information */
for (int planeIndex = 0; planeIndex < imagePlaneCount; planeIndex++) {
batchPlaneIndex = batchIndex * imagePlaneCount + planeIndex;
m_buffer[bufIndex].size[batchPlaneIndex] = 0;
m_buffer[bufIndex].bytesPerLine[batchPlaneIndex] = 0;
m_buffer[bufIndex].fd[batchPlaneIndex] = -1;
m_buffer[bufIndex].addr[batchPlaneIndex] = NULL;
}
/* Update buffer status */
enum EXYNOS_CAMERA_BUFFER_POSITION position = EXYNOS_CAMERA_BUFFER_POSITION_NONE;
enum EXYNOS_CAMERA_BUFFER_PERMISSION permission = EXYNOS_CAMERA_BUFFER_PERMISSION_AVAILABLE;
ret = updateStatus(dstBufferIndex, 0, position, permission);
if (ret != NO_ERROR) {
CLOGE("[B%d]Failed to updateStatus. position %d permission %d",
dstBufferIndex, position, permission);
/* Continue to handle the remained planes */
}
/* Push buffer to availableBufferIndexQ */
m_availableBufferIndexQLock.lock();
m_availableBufferIndexQ.push_back(dstBufferIndex);
m_availableBufferIndexQLock.unlock();
}
/* Move origianl image plane to first image plane */
for (int planeIndex = 0; planeIndex < imagePlaneCount; planeIndex++) {
batchPlaneIndex = (m_buffer[bufIndex].batchSize - 1) * imagePlaneCount + planeIndex;
m_buffer[bufIndex].size[planeIndex] = m_buffer[bufIndex].size[batchPlaneIndex];
m_buffer[bufIndex].bytesPerLine[planeIndex] = m_buffer[bufIndex].bytesPerLine[batchPlaneIndex];
m_buffer[bufIndex].fd[planeIndex] = m_buffer[bufIndex].fd[batchPlaneIndex];
m_buffer[bufIndex].addr[planeIndex] = m_buffer[bufIndex].addr[batchPlaneIndex];
}
return ret;
}
bool ExynosCameraBufferManager::m_isValidBatchBuffer(int bufIndex)
{
if (bufIndex < 0 || m_allocatedBufCount + m_indexOffset <= bufIndex) {
CLOGE("buffer Index in out of bound [bufIndex=%d], allocatedBufCount(%d)",
bufIndex, m_allocatedBufCount);
return false;
}
int imagePlaneCount = (m_hasMetaPlane == true ? (m_buffer[bufIndex].planeCount - 1)
: m_buffer[bufIndex].planeCount);
int originalPlaneIndex = (m_buffer[bufIndex].batchSize - 1) * imagePlaneCount;
bool isValid = (m_buffer[bufIndex].batchSize > 1)
&& (m_buffer[bufIndex].fd[0] != m_buffer[bufIndex].fd[originalPlaneIndex])
&& (m_buffer[bufIndex].fd[0] > -1);
return isValid;
}
int ExynosCameraBufferManager::getAllocatedBufferCount(void)
{
return m_allocatedBufCount;
}
int ExynosCameraBufferManager::getAvailableIncreaseBufferCount(void)
{
CLOGI("this function only applied to ONDEMAND mode (%d)", m_allocMode);
int numAvailable = 0;
if (m_allocMode == BUFFER_MANAGER_ALLOCATION_ONDEMAND)
numAvailable += (m_allowedMaxBufCount - m_allocatedBufCount);
CLOGI("m_allowedMaxBufCount(%d), m_allocatedBufCount(%d), ret(%d)",
m_allowedMaxBufCount, m_allocatedBufCount, numAvailable);
return numAvailable;
}
int ExynosCameraBufferManager::getNumOfAvailableBuffer(void)
{
int numAvailable = 0;
for (int i = m_indexOffset; i < m_allocatedBufCount + m_indexOffset; i++) {
if (m_buffer[i].status.permission == EXYNOS_CAMERA_BUFFER_PERMISSION_AVAILABLE)
numAvailable++;
}
if (m_allocMode == BUFFER_MANAGER_ALLOCATION_ONDEMAND)
numAvailable += (m_allowedMaxBufCount - m_allocatedBufCount);
return numAvailable;
}
int ExynosCameraBufferManager::getNumOfAvailableAndNoneBuffer(void)
{
int numAvailable = 0;
for (int i = m_indexOffset; i < m_allocatedBufCount + m_indexOffset; i++) {
if (m_buffer[i].status.permission == EXYNOS_CAMERA_BUFFER_PERMISSION_AVAILABLE ||
m_buffer[i].status.permission == EXYNOS_CAMERA_BUFFER_PERMISSION_NONE)
numAvailable++;
}
return numAvailable;
}
int ExynosCameraBufferManager::getNumOfAllowedMaxBuffer(void)
{
Mutex::Autolock lock(m_lock);
return m_allowedMaxBufCount;
}
void ExynosCameraBufferManager::printBufferState(void)
{
for (int i = m_indexOffset; i < m_allocatedBufCount + m_indexOffset; i++) {
CLOGI("m_buffer[%d].fd[0]=%d, position=%d, permission=%d]",
i, m_buffer[i].fd[0],
m_buffer[i].status.position, m_buffer[i].status.permission);
}
return;
}
void ExynosCameraBufferManager::printBufferState(int bufIndex, int planeIndex)
{
CLOGI("m_buffer[%d].fd[%d]=%d, .status.permission=%d]",
bufIndex, planeIndex, m_buffer[bufIndex].fd[planeIndex],
m_buffer[bufIndex].status.permission);
return;
}
void ExynosCameraBufferManager::printBufferQState()
{
List<int>::iterator r;
int bufferIndex;
Mutex::Autolock lock(m_availableBufferIndexQLock);
for (r = m_availableBufferIndexQ.begin(); r != m_availableBufferIndexQ.end(); r++) {
bufferIndex = *r;
CLOGV("bufferIndex=%d", bufferIndex);
}
return;
}
void ExynosCameraBufferManager::printBufferInfo(
const char *funcName,
const int lineNum,
int bufIndex,
int planeIndex)
{
CLOGI("[m_buffer[%d].fd[%d]=%d] .addr=%p .size=%d]",
bufIndex, planeIndex,
m_buffer[bufIndex].fd[planeIndex],
m_buffer[bufIndex].addr[planeIndex],
m_buffer[bufIndex].size[planeIndex]);
return;
}
void ExynosCameraBufferManager::dump(void)
{
CLOGD("----- dump buffer status -----");
printBufferState();
printBufferQState();
return;
}
void ExynosCameraBufferManager::dumpBufferInfo(void)
{
for (int bufIndex = m_indexOffset; bufIndex < m_allocatedBufCount + m_indexOffset; bufIndex++) {
int totalPlaneCount = m_getTotalPlaneCount(m_buffer[bufIndex].planeCount, m_buffer[bufIndex].batchSize, m_hasMetaPlane);
for (int planeIndex = 0; planeIndex < totalPlaneCount; planeIndex++) {
CLOGI("[m_buffer[%d].fd[%d]=%d] .addr=%p .size=%d .position=%d .permission=%d]",
m_buffer[bufIndex].index, planeIndex,
m_buffer[bufIndex].fd[planeIndex],
m_buffer[bufIndex].addr[planeIndex],
m_buffer[bufIndex].size[planeIndex],
m_buffer[bufIndex].status.position,
m_buffer[bufIndex].status.permission);
}
}
printBufferQState();
return;
}
status_t ExynosCameraBufferManager::setBufferCount(__unused int bufferCount)
{
CLOGD("");
return NO_ERROR;
}
int ExynosCameraBufferManager::getBufferCount(void)
{
CLOGV("");
return 0;
}
InternalExynosCameraBufferManager::InternalExynosCameraBufferManager()
{
ExynosCameraBufferManager::init();
}
InternalExynosCameraBufferManager::~InternalExynosCameraBufferManager()
{
ExynosCameraBufferManager::deinit();
}
status_t InternalExynosCameraBufferManager::m_setAllocator(void *allocator)
{
return m_setDefaultAllocator(allocator);
}
status_t InternalExynosCameraBufferManager::m_alloc(int bIndex, int eIndex)
{
return m_defaultAlloc(bIndex, eIndex, false);
}
status_t InternalExynosCameraBufferManager::m_free(int bIndex, int eIndex)
{
return m_defaultFree(bIndex, eIndex, false);
}
status_t InternalExynosCameraBufferManager::m_increase(int increaseCount)
{
CLOGD("IN..");
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
status_t ret = NO_ERROR;
if (m_allowedMaxBufCount <= m_allocatedBufCount) {
CLOGD("BufferManager can't increase the buffer "
"(m_reqBufCount=%d, m_allowedMaxBufCount=%d <= m_allocatedBufCount=%d)",
m_reqBufCount, m_allowedMaxBufCount, m_allocatedBufCount);
ret = INVALID_OPERATION;
goto func_exit;
}
if (m_allowedMaxBufCount < m_allocatedBufCount + increaseCount) {
CLOGI("change the increaseCount (%d->%d) --- "
"(m_reqBufCount=%d, m_allowedMaxBufCount=%d <= m_allocatedBufCount=%d + increaseCount=%d)",
increaseCount, m_allowedMaxBufCount - m_allocatedBufCount,
m_reqBufCount, m_allowedMaxBufCount, m_allocatedBufCount, increaseCount);
increaseCount = m_allowedMaxBufCount - m_allocatedBufCount;
}
/* set the buffer information */
for (int bufIndex = m_allocatedBufCount + m_indexOffset; bufIndex < m_allocatedBufCount + m_indexOffset + increaseCount; bufIndex++) {
for (int planeIndex = 0; planeIndex < m_buffer[0].planeCount; planeIndex++) {
if (m_buffer[0].size[planeIndex] == 0) {
CLOGE("abnormal value [size=%d]",
m_buffer[0].size[planeIndex]);
ret = BAD_VALUE;
goto func_exit;
}
m_buffer[bufIndex].size[planeIndex] = m_buffer[0].size[planeIndex];
m_buffer[bufIndex].bytesPerLine[planeIndex] = m_buffer[0].bytesPerLine[planeIndex];
}
m_buffer[bufIndex].planeCount = m_buffer[0].planeCount;
m_buffer[bufIndex].type = m_buffer[0].type;
}
if (m_alloc(m_allocatedBufCount + m_indexOffset, m_allocatedBufCount + m_indexOffset + increaseCount) != NO_ERROR) {
CLOGE("m_alloc failed");
ret = INVALID_OPERATION;
goto func_exit;
}
if (m_hasMetaPlane == true) {
if (m_defaultAlloc(m_allocatedBufCount + m_indexOffset, m_allocatedBufCount + m_indexOffset + increaseCount, m_hasMetaPlane) != NO_ERROR) {
CLOGE("m_defaultAlloc failed");
ret = INVALID_OPERATION;
goto func_exit;
}
}
CLOGD("Increase the buffer succeeded (m_allocatedBufCount=%d, increaseCount=%d)",
m_allocatedBufCount + m_indexOffset, increaseCount);
func_exit:
CLOGD("OUT..");
return ret;
}
status_t InternalExynosCameraBufferManager::m_decrease(void)
{
CLOGD("IN..");
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
status_t ret = true;
List<int>::iterator r;
int bufferIndex = -1;
if (m_allocatedBufCount <= m_reqBufCount) {
CLOGD("BufferManager can't decrease the buffer "
"(m_allowedMaxBufCount=%d, m_allocatedBufCount=%d <= m_reqBufCount=%d)",
m_allowedMaxBufCount, m_allocatedBufCount, m_reqBufCount);
ret = INVALID_OPERATION;
goto func_exit;
}
bufferIndex = m_allocatedBufCount;
if (m_free(bufferIndex-1 + m_indexOffset, bufferIndex + m_indexOffset) != NO_ERROR) {
CLOGE("m_free failed");
ret = INVALID_OPERATION;
goto func_exit;
}
if (m_hasMetaPlane == true) {
if (m_defaultFree(bufferIndex-1 + m_indexOffset, bufferIndex + m_indexOffset, m_hasMetaPlane) != NO_ERROR) {
CLOGE("m_defaultFree failed");
ret = INVALID_OPERATION;
goto func_exit;
}
}
m_availableBufferIndexQLock.lock();
for (r = m_availableBufferIndexQ.begin(); r != m_availableBufferIndexQ.end(); r++) {
if ((bufferIndex + m_indexOffset) == *r) {
m_availableBufferIndexQ.erase(r);
break;
}
}
m_availableBufferIndexQLock.unlock();
m_allocatedBufCount--;
CLOGD("Decrease the buffer succeeded (m_allocatedBufCount=%d)" ,
m_allocatedBufCount);
func_exit:
CLOGD("OUT..");
return ret;
}
status_t InternalExynosCameraBufferManager::m_putBuffer(__unused int bufIndex)
{
return NO_ERROR;
}
status_t InternalExynosCameraBufferManager::m_getBuffer(__unused int *bufIndex, __unused int *acquireFence, __unused int *releaseFence)
{
return NO_ERROR;
}
status_t InternalExynosCameraBufferManager::increase(int increaseCount)
{
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
Mutex::Autolock lock(m_lock);
status_t ret = NO_ERROR;
CLOGI("m_allocatedBufCount(%d), m_allowedMaxBufCount(%d), increaseCount(%d)",
m_allocatedBufCount, m_allowedMaxBufCount, increaseCount);
/* increase buffer*/
ret = m_increase(increaseCount);
if (ret < 0) {
CLOGE("increase the buffer failed, m_allocatedBufCount(%d), m_allowedMaxBufCount(%d), increaseCount(%d)",
m_allocatedBufCount, m_allowedMaxBufCount, increaseCount);
} else {
for (int bufferIndex = m_allocatedBufCount + m_indexOffset; bufferIndex < m_allocatedBufCount + m_indexOffset + increaseCount; bufferIndex++) {
m_availableBufferIndexQLock.lock();
m_availableBufferIndexQ.push_back(bufferIndex);
m_availableBufferIndexQLock.unlock();
}
m_allocatedBufCount += increaseCount;
dumpBufferInfo();
CLOGI("increase the buffer succeeded (increaseCount(%d))",
increaseCount);
}
func_exit:
return ret;
}
MHBExynosCameraBufferManager::MHBExynosCameraBufferManager()
{
ExynosCameraBufferManager::init();
m_allocator = NULL;
m_numBufsHeap = 1;
for (int bufIndex = m_indexOffset; bufIndex < VIDEO_MAX_FRAME; bufIndex++) {
for (int planeIndex = 0; planeIndex < EXYNOS_CAMERA_BUFFER_MAX_PLANES; planeIndex++) {
m_heap[bufIndex][planeIndex] = NULL;
}
}
}
MHBExynosCameraBufferManager::~MHBExynosCameraBufferManager()
{
ExynosCameraBufferManager::deinit();
}
status_t MHBExynosCameraBufferManager::m_setAllocator(void *allocator)
{
m_allocator = (ExynosCameraMHBAllocator *)allocator;
return NO_ERROR;
}
status_t MHBExynosCameraBufferManager::m_alloc(int bIndex, int eIndex)
{
EXYNOS_CAMERA_BUFFER_IN();
int planeCount = 0;
if (m_allocator == NULL) {
CLOGE("m_allocator equals NULL");
return INVALID_OPERATION;
}
for (int bufIndex = bIndex; bufIndex < eIndex; bufIndex++) {
planeCount = (m_hasMetaPlane ?
m_buffer[bufIndex].planeCount-1 : m_buffer[bufIndex].planeCount);
for (int planeIndex = 0; planeIndex < planeCount; planeIndex++) {
if (m_allocator->alloc(
m_buffer[bufIndex].size[planeIndex],
&(m_buffer[bufIndex].fd[planeIndex]),
&(m_buffer[bufIndex].addr[planeIndex]),
m_numBufsHeap,
&(m_heap[bufIndex][planeIndex])) != NO_ERROR) {
CLOGE("m_allocator->alloc(bufIndex=%d, planeIndex=%d, planeIndex=%d) failed",
bufIndex, planeIndex, m_buffer[bufIndex].size[planeIndex]);
return INVALID_OPERATION;
}
#ifdef EXYNOS_CAMERA_BUFFER_TRACE
printBufferInfo(__FUNCTION__, __LINE__, bufIndex, planeIndex);
CLOGI("[m_buffer[%d][%d].heap=%p]",
bufIndex, planeIndex, m_heap[bufIndex][planeIndex]);
#endif
}
if (updateStatus(
bufIndex,
0,
EXYNOS_CAMERA_BUFFER_POSITION_NONE,
EXYNOS_CAMERA_BUFFER_PERMISSION_AVAILABLE) != NO_ERROR) {
CLOGE("setStatus failed [bIndex=%d, position=NONE, permission=NONE]",
bufIndex);
return INVALID_OPERATION;
}
}
EXYNOS_CAMERA_BUFFER_OUT();
return NO_ERROR;
}
status_t MHBExynosCameraBufferManager::m_free(int bIndex, int eIndex)
{
EXYNOS_CAMERA_BUFFER_IN();
status_t ret = NO_ERROR;
int planeCount = 0;
for (int bufIndex = bIndex; bufIndex < eIndex; bufIndex++) {
if (isAvaliable(bufIndex) == false) {
CLOGE("buffer [bufIndex=%d] in InProcess state",
bufIndex);
if (m_isDestructor == false) {
ret = BAD_VALUE;
continue;
} else {
CLOGE("buffer [bufIndex=%d] in InProcess state, but try to forcedly free",
bufIndex);
}
}
planeCount = (m_hasMetaPlane ?
m_buffer[bufIndex].planeCount-1 : m_buffer[bufIndex].planeCount);
for (int planeIndex = 0; planeIndex < planeCount; planeIndex++) {
if (m_allocator->free(
m_buffer[bufIndex].size[planeIndex],
&(m_buffer[bufIndex].fd[planeIndex]),
&(m_buffer[bufIndex].addr[planeIndex]),
&(m_heap[bufIndex][planeIndex])) != NO_ERROR) {
CLOGE("m_defaultAllocator->free for Imagedata Plane failed");
ret = INVALID_OPERATION;
goto func_exit;
}
m_heap[bufIndex][planeIndex] = 0;
}
if (updateStatus(
bufIndex,
0,
EXYNOS_CAMERA_BUFFER_POSITION_NONE,
EXYNOS_CAMERA_BUFFER_PERMISSION_NONE) != NO_ERROR) {
CLOGE("setStatus failed [bIndex=%d, position=NONE, permission=NONE]",
bufIndex);
ret = INVALID_OPERATION;
goto func_exit;
}
if (m_graphicBufferAllocator.free(bufIndex) != NO_ERROR) {
CLOGE("m_graphicBufferAllocator.free(%d) fail",
bufIndex);
ret = INVALID_OPERATION;
goto func_exit;
}
}
func_exit:
EXYNOS_CAMERA_BUFFER_OUT();
return ret;
}
status_t MHBExynosCameraBufferManager::m_increase(__unused int increaseCount)
{
CLOGD("allocMode(%d) is invalid. Do nothing", m_allocMode);
return INVALID_OPERATION;
}
status_t MHBExynosCameraBufferManager::m_decrease(void)
{
return INVALID_OPERATION;
}
status_t MHBExynosCameraBufferManager::m_putBuffer(__unused int bufIndex)
{
return NO_ERROR;
}
status_t MHBExynosCameraBufferManager::m_getBuffer(__unused int *bufIndex, __unused int *acquireFence, __unused int *releaseFence)
{
return NO_ERROR;
}
status_t MHBExynosCameraBufferManager::allocMulti()
{
m_numBufsHeap = m_reqBufCount;
m_reqBufCount = 1;
return alloc();
}
status_t MHBExynosCameraBufferManager::getHeapMemory(
int bufIndex,
int planeIndex,
camera_memory_t **heap)
{
EXYNOS_CAMERA_BUFFER_IN();
if (m_buffer[bufIndex].status.position != EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL) {
CLOGE("buffer position not in IN_HAL");
return BAD_VALUE;
}
if (m_heap[bufIndex][planeIndex] == NULL) {
CLOGE("m_heap equals NULL");
return BAD_VALUE;
}
*heap = m_heap[bufIndex][planeIndex];
#ifdef EXYNOS_CAMERA_BUFFER_TRACE
CLOGI("heap=%p", *heap);
#endif
EXYNOS_CAMERA_BUFFER_OUT();
return NO_ERROR;
}
GrallocExynosCameraBufferManager::GrallocExynosCameraBufferManager()
{
ExynosCameraBufferManager::init();
m_allocator = NULL;
m_dequeuedBufCount = 0;
m_minUndequeuedBufCount = 0;
m_bufStride = 0;
m_bufferCount = 0;
#ifdef USE_GRALLOC_BUFFER_COLLECTOR
m_collectedBufferCount = 0;
m_stopBufferCollector = false;
m_bufferCollector = new grallocBufferThread(this, &GrallocExynosCameraBufferManager::m_bufferCollectorThreadFunc, "GrallocBufferCollector", PRIORITY_DEFAULT);
#endif
for (int bufIndex = 0; bufIndex < VIDEO_MAX_FRAME; bufIndex++) {
m_handle[bufIndex] = NULL;
m_handleIsLocked[bufIndex] = false;
}
}
GrallocExynosCameraBufferManager::~GrallocExynosCameraBufferManager()
{
ExynosCameraBufferManager::deinit();
}
status_t GrallocExynosCameraBufferManager::m_setAllocator(void *allocator)
{
m_allocator = (ExynosCameraGrallocAllocator *)allocator;
return NO_ERROR;
}
status_t GrallocExynosCameraBufferManager::m_alloc(int bIndex, int eIndex)
{
EXYNOS_CAMERA_BUFFER_IN();
status_t ret = NO_ERROR;
ExynosCameraDurationTimer m_timer;
long long durationTime = 0;
long long durationTimeSum = 0;
unsigned int estimatedBase = EXYNOS_CAMERA_BUFFER_GRALLOC_WARNING_TIME;
unsigned int estimatedTime = 0;
unsigned int bufferSize = 0;
int planeIndexEnd = 0;
if (m_allocator == NULL) {
CLOGE("m_allocator equals NULL");
ret = INVALID_OPERATION;
goto func_exit;
}
if (getBufferCount() == 0) {
CLOGE("m_reqBufCount(%d)", m_reqBufCount);
setBufferCount(m_reqBufCount);
}
m_minUndequeuedBufCount = m_allocator->getMinUndequeueBuffer();
if (m_minUndequeuedBufCount < 0 ) {
CLOGE("m_minUndequeuedBufCount=%d..",
m_minUndequeuedBufCount);
ret = INVALID_OPERATION;
goto func_exit;
}
#ifdef EXYNOS_CAMERA_BUFFER_TRACE
CLOGI("before dequeueBuffer m_reqBufCount=%d, m_minUndequeuedBufCount=%d",
m_reqBufCount, m_minUndequeuedBufCount);
#endif
for (int bufIndex = bIndex; bufIndex < eIndex; bufIndex++) {
m_timer.start();
if (m_allocator->alloc(
&m_handle[bufIndex],
m_buffer[bufIndex].fd,
m_buffer[bufIndex].addr,
&m_bufStride,
&m_handleIsLocked[bufIndex]) != NO_ERROR) {
CLOGE("ERR(%s[%d]):alloc failed [bufIndex=%d]",
__FUNCTION__, __LINE__, bufIndex);
ret = INVALID_OPERATION;
goto func_exit;
}
planeIndexEnd = m_buffer[bufIndex].planeCount;
if (m_hasMetaPlane == true)
planeIndexEnd--;
bufferSize = 0;
for (int planeIndex = 0; planeIndex < planeIndexEnd; planeIndex++) {
bufferSize = bufferSize + m_buffer[bufIndex].size[planeIndex];
/* Mirroring original plane to last plane */
if (m_buffer[bufIndex].batchSize > 1) {
int imagePlaneCount = (m_hasMetaPlane == true ? (m_buffer[bufIndex].planeCount - 1)
: m_buffer[bufIndex].planeCount);
int batchPlaneIndex = (m_buffer[bufIndex].batchSize - 1) * imagePlaneCount + planeIndex;
m_buffer[bufIndex].size[batchPlaneIndex] = m_buffer[bufIndex].size[planeIndex];
m_buffer[bufIndex].bytesPerLine[batchPlaneIndex] = m_buffer[bufIndex].bytesPerLine[planeIndex];
m_buffer[bufIndex].fd[batchPlaneIndex] = m_buffer[bufIndex].fd[planeIndex];
m_buffer[bufIndex].addr[batchPlaneIndex] = m_buffer[bufIndex].addr[planeIndex];
}
}
m_timer.stop();
durationTime = m_timer.durationMsecs();
durationTimeSum += durationTime;
CLOGD("duration time(%5d msec):(type=%d, bufIndex=%d, size=%.2f)",
(int)durationTime, m_buffer[bufIndex].type, bufIndex, (float)bufferSize / (float)(1024 * 1024));
estimatedTime = estimatedBase * bufferSize / EXYNOS_CAMERA_BUFFER_1MB;
if (estimatedTime < durationTime) {
CLOGW("estimated time(%5d msec):(type=%d, bufIndex=%d, size=%d)",
(int)estimatedTime, m_buffer[bufIndex].type, bufIndex, (int)bufferSize);
}
#ifdef EXYNOS_CAMERA_BUFFER_TRACE
dump();
#endif
m_dequeuedBufCount++;
if (updateStatus(
bufIndex,
0,
EXYNOS_CAMERA_BUFFER_POSITION_NONE,
EXYNOS_CAMERA_BUFFER_PERMISSION_AVAILABLE) != NO_ERROR) {
CLOGE("setStatus failed [bufIndex=%d, position=NONE, permission=NONE]",
bufIndex);
ret = INVALID_OPERATION;
goto func_exit;
}
}
if (planeIndexEnd == 1) {
CLOGD("Duration time of buffer(Plane:0) allocation(%5d msec)", (int)durationTimeSum);
} else if (planeIndexEnd > 1) {
CLOGD("Duration time of buffer(Plane:0~%d) allocation(%5d msec)",
(planeIndexEnd - 1), (int)durationTimeSum);
}
for (int bufIndex = bIndex; bufIndex < eIndex; bufIndex++) {
#ifdef USE_GRALLOC_REUSE_SUPPORT
m_cancelReuseBuffer(bufIndex, true);
#else
#ifdef EXYNOS_CAMERA_BUFFER_TRACE
dump();
#endif
if (m_allocator->cancelBuffer(m_handle[bufIndex], &m_lock) != 0) {
CLOGE("ERR(%s[%d]):could not free [bufIndex=%d]",
__FUNCTION__, __LINE__, bufIndex);
goto func_exit;
}
m_handleIsLocked[bufIndex] = false;
m_dequeuedBufCount--;
if (updateStatus(
bufIndex,
0,
EXYNOS_CAMERA_BUFFER_POSITION_NONE,
EXYNOS_CAMERA_BUFFER_PERMISSION_NONE) != NO_ERROR) {
CLOGE("setStatus failed [bufIndex=%d, position=NONE, permission=NONE]",
bufIndex);
ret = INVALID_OPERATION;
goto func_exit;
}
#endif
}
#ifdef USE_GRALLOC_BUFFER_COLLECTOR
m_bufferCollector->run();
#endif
#ifdef EXYNOS_CAMERA_BUFFER_TRACE
CLOGI("before exit m_alloc m_dequeuedBufCount=%d, m_minUndequeuedBufCount=%d",
m_dequeuedBufCount, m_minUndequeuedBufCount);
#endif
func_exit:
EXYNOS_CAMERA_BUFFER_OUT();
return ret;
}
status_t GrallocExynosCameraBufferManager::m_free(int bIndex, int eIndex)
{
EXYNOS_CAMERA_BUFFER_IN();
status_t ret = NO_ERROR;
dump();
for (int bufIndex = bIndex; bufIndex < eIndex; bufIndex++) {
if (m_handleIsLocked[bufIndex] == false) {
CLOGD("buffer [bufIndex=%d] already free",
bufIndex);
continue;
}
if (m_allocator->free(m_handle[bufIndex], m_handleIsLocked[bufIndex]) != 0) {
CLOGE("could not free [bufIndex=%d]",
bufIndex);
goto func_exit;
}
m_handle[bufIndex] = NULL;
m_handleIsLocked[bufIndex] = false;
m_dequeuedBufCount--;
/* Clear the mirrored last plane */
if (m_buffer[bufIndex].batchSize > 1) {
int imagePlaneCount = (m_hasMetaPlane == true ? (m_buffer[bufIndex].planeCount - 1)
: m_buffer[bufIndex].planeCount);
for (int planeIndex = 0; planeIndex < imagePlaneCount; planeIndex++) {
int batchPlaneIndex = (m_buffer[bufIndex].batchSize - 1) * imagePlaneCount + planeIndex;
m_buffer[bufIndex].size[batchPlaneIndex] = 0;
m_buffer[bufIndex].bytesPerLine[batchPlaneIndex] = 0;
m_buffer[bufIndex].fd[batchPlaneIndex] = -1;
m_buffer[bufIndex].addr[batchPlaneIndex] = 0;
}
}
if (updateStatus(
bufIndex,
0,
EXYNOS_CAMERA_BUFFER_POSITION_NONE,
EXYNOS_CAMERA_BUFFER_PERMISSION_NONE) != NO_ERROR) {
CLOGE("setStatus failed [bIndex=%d, position=NONE, permission=NONE]",
bufIndex);
ret = INVALID_OPERATION;
goto func_exit;
}
if (m_graphicBufferAllocator.free(bufIndex) != NO_ERROR) {
CLOGE("m_graphicBufferAllocator.free(%d) fail",
bufIndex);
ret = INVALID_OPERATION;
goto func_exit;
}
}
func_exit:
EXYNOS_CAMERA_BUFFER_OUT();
return ret;
}
status_t GrallocExynosCameraBufferManager::m_increase(__unused int increaseCount)
{
CLOGD("allocMode(%d) is invalid. Do nothing", m_allocMode);
return INVALID_OPERATION;
}
status_t GrallocExynosCameraBufferManager::m_decrease(void)
{
return INVALID_OPERATION;
}
status_t GrallocExynosCameraBufferManager::m_putBuffer(int bufIndex)
{
EXYNOS_CAMERA_BUFFER_IN();
status_t ret = NO_ERROR;
if (m_handle[bufIndex] != NULL
&& m_buffer[bufIndex].status.position == EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL) {
ret = m_allocator->enqueueBuffer(m_handle[bufIndex], &m_lock);
if (ret != NO_ERROR) {
CLOGE("could not enqueue_buffer [bufIndex=%d]",
bufIndex);
dump();
goto func_exit;
}
m_handle[bufIndex] = NULL;
m_handleIsLocked[bufIndex] = false;
m_dequeuedBufCount--;
m_buffer[bufIndex].status.position = EXYNOS_CAMERA_BUFFER_POSITION_IN_SERVICE;
}
#ifdef EXYNOS_CAMERA_BUFFER_TRACE
dump();
#endif
func_exit:
EXYNOS_CAMERA_BUFFER_OUT();
return ret;
}
status_t GrallocExynosCameraBufferManager::m_getBuffer(int *bufIndex, __unused int *acquireFence, __unused int *releaseFence)
{
EXYNOS_CAMERA_BUFFER_IN();
status_t ret = NO_ERROR;
buffer_handle_t *bufHandle = NULL;
int bufferFd[3] = {0};
void *bufferAddr[3] = {NULL};
int stride = 0;
int bufferIndex = -1;
const private_handle_t *priv_handle;
bool isExistedBuffer = false;
bool isLocked = false;
#ifdef USE_GRALLOC_BUFFER_COLLECTOR
/* Error return check is done by callee */
ret = m_getCollectedBuffer(bufIndex);
#else /* USE_GRALLOC_BUFFER_COLLECTOR */
m_minUndequeuedBufCount = m_allocator->getMinUndequeueBuffer();
if (m_minUndequeuedBufCount < 0 ) {
CLOGE("m_minUndequeuedBufCount=%d..",
m_minUndequeuedBufCount);
ret = INVALID_OPERATION;
goto func_exit;
}
if (m_dequeuedBufCount == m_reqBufCount - m_minUndequeuedBufCount) {
CLOGI("skip allocation... ");
CLOGI("m_dequeuedBufCount(%d) == m_reqBufCount(%d) - m_minUndequeuedBufCount(%d)",
m_dequeuedBufCount, m_reqBufCount, m_minUndequeuedBufCount);
dump();
ret = INVALID_OPERATION;
goto func_exit;
}
#ifdef EXYNOS_CAMERA_BUFFER_TRACE
CLOGD("before dequeueBuffer() "
"m_reqBufCount=%d, m_dequeuedBufCount=%d, m_minUndequeuedBufCount=%d",
m_reqBufCount, m_dequeuedBufCount, m_minUndequeuedBufCount);
#endif
if (m_allocator->dequeueBuffer(
&bufHandle,
bufferFd,
(char **)bufferAddr,
&isLocked, &m_lock) != NO_ERROR) {
CLOGE("dequeueBuffer failed");
ret = INVALID_OPERATION;
goto func_exit;
}
if (m_indexOffset < 0 || VIDEO_MAX_FRAME < (m_reqBufCount + m_indexOffset)) {
CLOGE("abnormal value [m_indexOffset=%d, m_reqBufCount=%d]",
m_indexOffset, m_reqBufCount);
ret = BAD_VALUE;
goto func_exit;
}
for (int index = m_indexOffset; index < m_reqBufCount + m_indexOffset; index++) {
if (m_buffer[index].addr[0] != bufferAddr[0]) {
continue;
} else {
bufferIndex = index;
isExistedBuffer = true;
#ifdef EXYNOS_CAMERA_BUFFER_TRACE
CLOGI("bufferIndex(%d) found!", bufferIndex);
#endif
break;
}
}
if (isExistedBuffer == false) {
CLOGI("not existedBuffer!");
if (m_allocator->cancelBuffer(bufHandle, &m_lock) != 0) {
CLOGE("could not cancelBuffer [bufferIndex=%d]",
bufferIndex);
}
ret = BAD_VALUE;
goto func_exit;
}
if (bufferIndex < 0 || VIDEO_MAX_FRAME <= bufferIndex) {
CLOGE("abnormal value [bufferIndex=%d]",
bufferIndex);
ret = BAD_VALUE;
goto func_exit;
}
priv_handle = private_handle_t::dynamicCast(*bufHandle);
if (m_hasMetaPlane == true) {
switch (m_buffer[bufferIndex].planeCount) {
case 3:
m_buffer[bufferIndex].fd[1] = priv_handle->fd1;
m_buffer[bufferIndex].addr[1] = (char *)bufferAddr[1];
/* no break; */
case 2:
m_buffer[bufferIndex].fd[0] = priv_handle->fd;
m_buffer[bufferIndex].addr[0] = (char *)bufferAddr[0];
break;
default:
android_printAssert(NULL, LOG_TAG, "ASSERT(%s[%d]):invalid m_buffer[%d].planeCount(%d) with metaPlane, assert!!!!",
__FUNCTION__, __LINE__, bufferIndex, m_buffer[bufferIndex].planeCount);
break;
}
} else {
switch (m_buffer[bufferIndex].planeCount) {
case 3:
m_buffer[bufferIndex].fd[2] = priv_handle->fd2;
m_buffer[bufferIndex].addr[2] = (char *)bufferAddr[2];
/* no break; */
case 2:
m_buffer[bufferIndex].fd[1] = priv_handle->fd1;
m_buffer[bufferIndex].addr[1] = (char *)bufferAddr[1];
/* no break; */
case 1:
m_buffer[bufferIndex].fd[0] = priv_handle->fd;
m_buffer[bufferIndex].addr[0] = (char *)bufferAddr[0];
break;
default:
android_printAssert(NULL, LOG_TAG, "ASSERT(%s[%d]):invalid m_buffer[%d].planeCount(%d) without metaPlane, assert!!!!",
__FUNCTION__, __LINE__, bufferIndex, m_buffer[bufferIndex].planeCount);
}
}
*bufIndex = bufferIndex;
m_handleIsLocked[bufferIndex] = isLocked;
m_handle[bufferIndex] = bufHandle;
m_dequeuedBufCount++;
m_buffer[bufferIndex].status.position = EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL;
m_buffer[bufferIndex].status.permission = EXYNOS_CAMERA_BUFFER_PERMISSION_AVAILABLE;
#endif /* NOT USE_GRALLOC_BUFFER_COLLECTOR */
#ifdef EXYNOS_CAMERA_BUFFER_TRACE
dump();
CLOGI("-- OUT -- m_dequeuedBufCount=%d, m_minUndequeuedBufCount=%d",
m_dequeuedBufCount, m_minUndequeuedBufCount);
#endif
func_exit:
EXYNOS_CAMERA_BUFFER_OUT();
return ret;
}
#ifdef USE_GRALLOC_REUSE_SUPPORT
bool GrallocExynosCameraBufferManager::m_cancelReuseBuffer(int bufIndex, bool isReuse)
{
bool ret = false;
bool found = false;
List<int>::iterator r;
int item = -1;
int maxCount = -1;
if (isReuse == true) {
m_availableBufferIndexQLock.lock();
for (r = m_availableBufferIndexQ.begin(); r != m_availableBufferIndexQ.end(); r++) {
if (bufIndex == *r) {
found = true;
break;
}
}
if (found == true) {
CLOGV("bufIndex=%d is already in (available state)",
bufIndex);
m_availableBufferIndexQLock.unlock();
CLOGI("cancelReuse not available buffer is founded [bufIndex=%d]", bufIndex);
ret = true;
return ret;
} else {
m_availableBufferIndexQ.push_back(m_buffer[bufIndex].index);
}
m_availableBufferIndexQLock.unlock();
m_buffer[bufIndex].status.position = EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL;
m_buffer[bufIndex].status.permission = EXYNOS_CAMERA_BUFFER_PERMISSION_AVAILABLE;
m_handleIsLocked[bufIndex] = true;
#ifdef USE_GRALLOC_BUFFER_COLLECTOR
m_collectedBufferCount++;
#endif
ret = true;
}
return ret;
}
#endif
#ifdef USE_GRALLOC_REUSE_SUPPORT
status_t GrallocExynosCameraBufferManager::cancelBuffer(int bufIndex, bool isReuse)
#else
status_t GrallocExynosCameraBufferManager::cancelBuffer(int bufIndex)
#endif
{
EXYNOS_CAMERA_BUFFER_IN();
status_t ret = NO_ERROR;
Mutex::Autolock lock(m_lock);
if (m_isValidBatchBuffer(bufIndex) == true) {
ret = m_destructBatchBuffer(bufIndex);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):[B%d]Failed to destructBatchBuffer. batchSize %d",
__FUNCTION__, __LINE__,
bufIndex, m_buffer[bufIndex].batchSize);
/* Continue to handle buffer as a single buffer */
}
}
#ifdef USE_GRALLOC_REUSE_SUPPORT
ret = m_cancelBuffer(bufIndex, isReuse);
#else
ret = m_cancelBuffer(bufIndex);
#endif
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):[B%d]Failed to cancelBuffer",
__FUNCTION__, __LINE__,
bufIndex);
/* Error code will be returned */
}
EXYNOS_CAMERA_BUFFER_OUT();
return ret;
}
#ifdef USE_GRALLOC_REUSE_SUPPORT
status_t GrallocExynosCameraBufferManager::m_cancelBuffer(int bufIndex, bool isReuse)
#else
status_t GrallocExynosCameraBufferManager::m_cancelBuffer(int bufIndex)
#endif
{
status_t ret = NO_ERROR;
List<int>::iterator r;
bool found = false;
#ifdef USE_GRALLOC_REUSE_SUPPORT
bool reuseRet = false;
#endif
if (bufIndex < 0 || m_reqBufCount + m_indexOffset <= bufIndex) {
CLOGE("buffer Index in out of bound [bufIndex=%d]",
bufIndex);
ret = INVALID_OPERATION;
goto func_exit;
}
if (m_handleIsLocked[bufIndex] == false) {
CLOGV("buffer [bufIndex=%d] already free", bufIndex);
return ret;
}
#ifdef USE_GRALLOC_REUSE_SUPPORT
reuseRet = m_cancelReuseBuffer(bufIndex, isReuse);
if (reuseRet == true) {
goto func_exit;
}
#endif
if (m_allocator->cancelBuffer(m_handle[bufIndex], &m_lock) != 0) {
CLOGE("could not cancel buffer [bufIndex=%d]", bufIndex);
goto func_exit;
}
m_dequeuedBufCount--;
m_handle[bufIndex] = NULL;
m_handleIsLocked[bufIndex] = false;
if (updateStatus(
bufIndex,
0,
EXYNOS_CAMERA_BUFFER_POSITION_NONE,
EXYNOS_CAMERA_BUFFER_PERMISSION_NONE) != NO_ERROR) {
CLOGE("setStatus failed [bIndex=%d, position=NONE, permission=NONE]",
bufIndex);
ret = INVALID_OPERATION;
goto func_exit;
}
m_availableBufferIndexQLock.lock();
for (r = m_availableBufferIndexQ.begin(); r != m_availableBufferIndexQ.end(); r++) {
if (bufIndex == *r) {
found = true;
break;
}
}
if (found == true) {
CLOGV("bufIndex=%d is already in (available state)",
bufIndex);
m_availableBufferIndexQLock.unlock();
goto func_exit;
}
m_availableBufferIndexQ.push_back(m_buffer[bufIndex].index);
m_availableBufferIndexQLock.unlock();
func_exit:
#ifdef EXYNOS_CAMERA_BUFFER_TRACE
dump();
#endif
return ret;
}
status_t GrallocExynosCameraBufferManager::m_constructBatchBuffer(int bufIndex)
{
status_t ret = NO_ERROR;
#ifdef USE_GRALLOC_BUFFER_COLLECTOR
if (m_collectedBufferCount < m_buffer[bufIndex].batchSize - 1)
#else
if (getNumOfAvailableAndNoneBuffer() < m_buffer[bufIndex].batchSize - 1)
#endif
{
CLOGW("NOT enough buffer for constructBatchBuffer.\
batchSize %d availableBuffer %d",
m_buffer[bufIndex].batchSize,
getNumOfAvailableAndNoneBuffer());
return INVALID_OPERATION;
}
/* Move original image plane to last image plane */
int imagePlaneCount = (m_hasMetaPlane == true ? (m_buffer[bufIndex].planeCount - 1)
: m_buffer[bufIndex].planeCount);
int batchPlaneIndex = 0;
for (int planeIndex = 0; planeIndex < imagePlaneCount; planeIndex++) {
batchPlaneIndex = (m_buffer[bufIndex].batchSize - 1) * imagePlaneCount + planeIndex;
m_buffer[bufIndex].size[batchPlaneIndex] = m_buffer[bufIndex].size[planeIndex];
m_buffer[bufIndex].bytesPerLine[batchPlaneIndex] = m_buffer[bufIndex].bytesPerLine[planeIndex];
m_buffer[bufIndex].fd[batchPlaneIndex] = m_buffer[bufIndex].fd[planeIndex];
m_buffer[bufIndex].addr[batchPlaneIndex] = m_buffer[bufIndex].addr[planeIndex];
}
for (int batchIndex = 0; batchIndex < m_buffer[bufIndex].batchSize - 1; batchIndex++) {
int srcBufferIndex = -1;
int acquireFence = -1;
int releaseFence = -1;
/* Get available buffer */
ret = m_getBuffer(&srcBufferIndex, &acquireFence, &releaseFence);
if (ret != NO_ERROR
|| srcBufferIndex < 0
|| m_allocatedBufCount + m_indexOffset <= srcBufferIndex) {
CLOGE("[B%d]Failed to getBuffer. srcBufferIndex %d",
bufIndex, srcBufferIndex);
return INVALID_OPERATION;
}
/* Erase buffer from availableBufferIndexQ */
m_availableBufferIndexQLock.lock();
for (List<int>::iterator r = m_availableBufferIndexQ.begin(); r != m_availableBufferIndexQ.end(); r++) {
if (srcBufferIndex == *r) {
m_availableBufferIndexQ.erase(r);
break;
}
}
m_availableBufferIndexQLock.unlock();
/* Check buffer validation */
if (isAvaliable(srcBufferIndex) == false) {
CLOGE("[B%d]isAvailable failed",
srcBufferIndex);
return INVALID_OPERATION;
}
/* Update buffer status */
enum EXYNOS_CAMERA_BUFFER_POSITION position = EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL;
enum EXYNOS_CAMERA_BUFFER_PERMISSION permission = EXYNOS_CAMERA_BUFFER_PERMISSION_IN_PROCESS;
ret = updateStatus(srcBufferIndex, 0, position, permission);
if (ret != NO_ERROR) {
CLOGE("[B%d]Failed to updateStatus. position %d, permission %d",
srcBufferIndex, position, permission);
return ret;
}
#ifdef USE_GRALLOC_BUFFER_COLLECTOR
CLOGV("[B%d]SrcBufferIndex %d BatchIndex %d Available %d Collected %d",
bufIndex,
srcBufferIndex, batchIndex,
getNumOfAvailableBuffer(),
m_collectedBufferCount);
#endif
/* Move plane information into batch buffer */
for (int planeIndex = 0; planeIndex < imagePlaneCount; planeIndex++) {
batchPlaneIndex = batchIndex * imagePlaneCount + planeIndex;
m_buffer[bufIndex].size[batchPlaneIndex] = m_buffer[srcBufferIndex].size[planeIndex];
m_buffer[bufIndex].bytesPerLine[batchPlaneIndex] = m_buffer[srcBufferIndex].bytesPerLine[planeIndex];
m_buffer[bufIndex].fd[batchPlaneIndex] = m_buffer[srcBufferIndex].fd[planeIndex];
m_buffer[bufIndex].addr[batchPlaneIndex] = m_buffer[srcBufferIndex].addr[planeIndex];
}
}
return ret;
}
status_t GrallocExynosCameraBufferManager::m_destructBatchBuffer(int bufIndex)
{
status_t ret = NO_ERROR;
int imagePlaneCount = (m_hasMetaPlane == true ? (m_buffer[bufIndex].planeCount - 1)
: m_buffer[bufIndex].planeCount);
int batchPlaneIndex = 0;
for (int batchIndex = 0; batchIndex < m_buffer[bufIndex].batchSize - 1; batchIndex++) {
int dstBufferIndex = -1;
/* Find buffer index by fd */
batchPlaneIndex = batchIndex * imagePlaneCount;
ret = getIndexByFd(m_buffer[bufIndex].fd[batchPlaneIndex], &dstBufferIndex);
if (ret != NO_ERROR
|| dstBufferIndex < 0
|| m_allocatedBufCount + m_indexOffset <= dstBufferIndex) {
CLOGE("ERR(%s[%d]:[B%d]Failed to getIndexByFd %d, dstBufferIndex %d, batchIndex %d, batchSize %d",
__FUNCTION__, __LINE__,
bufIndex,
m_buffer[bufIndex].fd[batchPlaneIndex],
dstBufferIndex,
batchPlaneIndex,
m_buffer[bufIndex].batchSize);
/* Continue to handle the remained planes */
continue;
}
#ifdef USE_GRALLOC_BUFFER_COLLECTOR
CLOGV("[B%d]DstBufferIndex %d BatchIndex %d Available %d Collected %d",
bufIndex,
dstBufferIndex, batchIndex,
getNumOfAvailableBuffer(),
m_collectedBufferCount);
#endif
/* Clear batch buffer information */
for (int planeIndex = 0; planeIndex < imagePlaneCount; planeIndex++) {
batchPlaneIndex = batchIndex * imagePlaneCount + planeIndex;
m_buffer[bufIndex].size[batchPlaneIndex] = 0;
m_buffer[bufIndex].bytesPerLine[batchPlaneIndex] = 0;
m_buffer[bufIndex].fd[batchPlaneIndex] = -1;
m_buffer[bufIndex].addr[batchPlaneIndex] = NULL;
}
/* Return buffer */
#ifdef USE_GRALLOC_REUSE_SUPPORT
ret = m_cancelBuffer(dstBufferIndex, true);
#else
ret = m_cancelBuffer(dstBufferIndex);
#endif
if (ret != NO_ERROR) {
CLOGE("[B%d]Failed to cancelBuffer.",
dstBufferIndex);
/* Error code is going to be returned */
}
}
/* Move origianl image plane to first image plane */
for (int planeIndex = 0; planeIndex < imagePlaneCount; planeIndex++) {
batchPlaneIndex = (m_buffer[bufIndex].batchSize - 1) * imagePlaneCount + planeIndex;
m_buffer[bufIndex].size[planeIndex] = m_buffer[bufIndex].size[batchPlaneIndex];
m_buffer[bufIndex].bytesPerLine[planeIndex] = m_buffer[bufIndex].bytesPerLine[batchPlaneIndex];
m_buffer[bufIndex].fd[planeIndex] = m_buffer[bufIndex].fd[batchPlaneIndex];
m_buffer[bufIndex].addr[planeIndex] = m_buffer[bufIndex].addr[batchPlaneIndex];
}
return ret;
}
void GrallocExynosCameraBufferManager::deinit(void)
{
CLOGD("IN..");
#ifdef USE_GRALLOC_BUFFER_COLLECTOR
/* declare thread will stop */
m_stopBufferCollector = true;
#endif
ExynosCameraBufferManager::deinit();
#ifdef USE_GRALLOC_BUFFER_COLLECTOR
/* thread stop */
m_bufferCollector->requestExitAndWait();
/* after thread end, reset m_stopBufferCollector as default */
m_stopBufferCollector = false;
#endif
CLOGD("OUT..");
}
status_t GrallocExynosCameraBufferManager::resetBuffers(void)
{
CLOGD("IN..");
status_t ret = NO_ERROR;
#ifdef USE_GRALLOC_BUFFER_COLLECTOR
/* declare thread will stop */
m_stopBufferCollector = true;
#endif
ret = ExynosCameraBufferManager::resetBuffers();
if (ret != NO_ERROR) {
CLOGE("ExynosCameraBufferManager::resetBuffers()");
}
#ifdef USE_GRALLOC_BUFFER_COLLECTOR
/* thread stop */
m_bufferCollector->requestExitAndWait();
/* after thread end, reset m_stopBufferCollector as default */
m_stopBufferCollector = false;
#endif
CLOGD("OUT..");
return ret;
}
status_t GrallocExynosCameraBufferManager::setBufferCount(int bufferCount)
{
CLOGD("");
status_t ret = NO_ERROR;
ret = resetBuffers();
if (ret != NO_ERROR) {
CLOGE("resetBuffers() failed");
goto func_exit;
}
ret = m_allocator->setBufferCount(bufferCount);
if (ret != NO_ERROR) {
CLOGE("m_allocator->setBufferCount(m_bufferCount(%d) -> %d)",
m_bufferCount, bufferCount);
goto func_exit;
}
m_bufferCount = bufferCount;
func_exit:
return ret;
}
int GrallocExynosCameraBufferManager::getBufferCount(void)
{
CLOGD("");
return m_bufferCount;
}
int GrallocExynosCameraBufferManager::getBufStride(void)
{
CLOGI("bufStride=%d", m_bufStride);
return m_bufStride;
}
void GrallocExynosCameraBufferManager::printBufferState(void)
{
for (int i = 0; i < m_allocatedBufCount; i++) {
CLOGI("m_buffer[%d].fd[0]=%d, position=%d, permission=%d, lock=%d]",
i, m_buffer[i].fd[0],
m_buffer[i].status.position, m_buffer[i].status.permission, m_handleIsLocked[i]);
}
return;
}
void GrallocExynosCameraBufferManager::printBufferState(int bufIndex, int planeIndex)
{
CLOGI("m_buffer[%d].fd[%d]=%d, .status.permission=%d, lock=%d]",
bufIndex, planeIndex, m_buffer[bufIndex].fd[planeIndex],
m_buffer[bufIndex].status.permission, m_handleIsLocked[bufIndex]);
return;
}
sp<GraphicBuffer> GrallocExynosCameraBufferManager::getGraphicBuffer(int index)
{
EXYNOS_CAMERA_BUFFER_IN();
sp<GraphicBuffer> graphicBuffer;
int width, height, stride;
int planeCount = 0;
if ((index < 0) || (index >= m_allowedMaxBufCount)) {
CLOGE("Buffer index error (%d/%d)", index, m_allowedMaxBufCount);
goto done;
}
if (m_graphicBufferAllocator.getSize(&width, &height, &stride) != NO_ERROR) {
CLOGE("m_graphicBufferAllocator.getSize(%d) fail", index);
goto done;
}
if (m_graphicBufferAllocator.setSize(width, height, m_bufStride) != NO_ERROR) {
CLOGE("m_graphicBufferAllocator.setSize(%d) fail", index);
goto done;
}
if (m_graphicBufferAllocator.setGrallocUsage(m_allocator->getGrallocUsage()) != NO_ERROR) {
CLOGE("m_graphicBufferAllocator.setGrallocUsage(%d) fail", index);
goto done;
}
planeCount = m_buffer[index].planeCount;
if (m_hasMetaPlane == true) {
planeCount--;
}
graphicBuffer = m_graphicBufferAllocator.alloc(index, planeCount, m_buffer[index].fd, m_buffer[index].addr, m_buffer[index].size);
if (graphicBuffer == 0) {
CLOGE("m_graphicBufferAllocator.alloc(%d) fail", index);
goto done;
}
done:
EXYNOS_CAMERA_BUFFER_OUT();
return graphicBuffer;
}
#ifdef USE_GRALLOC_BUFFER_COLLECTOR
bool GrallocExynosCameraBufferManager::m_bufferCollectorThreadFunc(void)
{
EXYNOS_CAMERA_BUFFER_IN();
status_t ret = NO_ERROR;
buffer_handle_t *bufHandle = NULL;
int bufferFd[3] = {0};
void *bufferAddr[3] = {NULL};
int stride = 0;
int bufferIndex = -1;
const private_handle_t *priv_handle;
bool isExistedBuffer = false;
bool isLocked = false;
uint8_t tryCount = 0;
if (m_stopBufferCollector == true) {
CLOGD("m_stopBufferCollector == true. so, just return. m_collectedBufferCount(%d)",
m_collectedBufferCount);
return false;
}
if (m_collectedBufferCount >= (m_allowedMaxBufCount - m_minUndequeuedBufCount - BUFFER_COLLECT_MARGIN)
|| m_dequeuedBufCount >= (m_allowedMaxBufCount - m_minUndequeuedBufCount)
) {
#ifdef EXYNOS_CAMERA_BUFFER_TRACE
CLOGD(" bufferCollector just return. m_collectedBufferCount(%d) m_dequeuedBufCount(%d)",
m_collectedBufferCount, m_dequeuedBufCount);
#endif
goto EXIT;
}
/* Blocking Function :
If the Gralloc buffer queue can not give the available buffer,
it will be blocked until the buffer which is being rendered
is released.
*/
{ // Autolock scope
Mutex::Autolock lock(m_lock);
ret = m_allocator->dequeueBuffer(&bufHandle,
bufferFd,
(char **) bufferAddr,
&isLocked, &m_lock);
} // Autolock scope
if (ret == NO_INIT) {
CLOGW("BufferQueue is abandoned!");
return false;
} else if (ret != NO_ERROR) {
CLOGE("dequeueBuffer failed, dequeue(%d), collected(%d)",
m_dequeuedBufCount, m_collectedBufferCount);
goto EXIT;
} else if (bufHandle == NULL) {
CLOGE("Buffer handle is NULL, dequeue(%d), collected(%d)",
m_dequeuedBufCount, m_collectedBufferCount);
goto EXIT;
}
if (m_indexOffset < 0 || VIDEO_MAX_FRAME < (m_reqBufCount + m_indexOffset)) {
CLOGE("abnormal value [m_indexOffset=%d, m_reqBufCount=%d]",
m_indexOffset, m_reqBufCount);
goto EXIT;
}
for (int index = m_indexOffset; index < m_reqBufCount + m_indexOffset; index++) {
int imagePlaneCount = (m_hasMetaPlane == true ? (m_buffer[index].planeCount - 1)
: m_buffer[index].planeCount);
int batchPlaneIndex = (m_buffer[index].batchSize - 1) * imagePlaneCount;
if (m_buffer[index].addr[batchPlaneIndex] != bufferAddr[0]) {
continue;
} else {
bufferIndex = index;
isExistedBuffer = true;
#ifdef EXYNOS_CAMERA_BUFFER_TRACE
CLOGI("bufferIndex(%d) found!", bufferIndex);
#endif
break;
}
}
if (isExistedBuffer == false) {
CLOGI("not existedBuffer!");
m_lock.lock();
if (m_allocator->cancelBuffer(bufHandle, &m_lock) != 0) {
CLOGE("could not cancelBuffer [bufferIndex=%d]",
bufferIndex);
}
m_lock.unlock();
goto EXIT;
}
if (m_stopBufferCollector == true) {
CLOGD("m_stopBufferCollector == true. so, just cancel. m_collectedBufferCount(%d)",
m_collectedBufferCount);
m_lock.lock();
if (m_allocator->cancelBuffer(bufHandle, &m_lock) != 0) {
CLOGE("could not cancelBuffer [bufferIndex=%d]",
bufferIndex);
}
m_lock.unlock();
return false;
}
if (bufferIndex < 0 || VIDEO_MAX_FRAME <= bufferIndex) {
CLOGE("abnormal value [bufferIndex=%d]",
bufferIndex);
goto EXIT;
}
priv_handle = private_handle_t::dynamicCast(*bufHandle);
{
/*
* this is mutex for race-condition with cancelBuffer()
* problem scenario.
* a. cancelBuffer() : cancelBuffer done -> context switch ->
* b. m_preDequeueThreadFunc(): dequeueBuffer done -> m_handleIsLocked[bufferIndex] = true -> context switch ->
* c. cancelBuffer() : m_handleIsLocked[bufferIndex] = false
* d. and next cancelBuffer() is fail, and lost that buffer forever.
*/
m_lock.lock();
if (m_hasMetaPlane == true) {
switch (m_buffer[bufferIndex].planeCount) {
case 3:
m_buffer[bufferIndex].fd[1] = priv_handle->fd1;
m_buffer[bufferIndex].addr[1] = (char *)bufferAddr[1];
/* no break; */
case 2:
m_buffer[bufferIndex].fd[0] = priv_handle->fd;
m_buffer[bufferIndex].addr[0] = (char *)bufferAddr[0];
break;
default:
android_printAssert(NULL, LOG_TAG, "ASSERT(%s[%d]):invalid m_buffer[%d].planeCount(%d) with metaPlane, assert!!!!",
__FUNCTION__, __LINE__, bufferIndex, m_buffer[bufferIndex].planeCount);
break;
}
} else {
switch (m_buffer[bufferIndex].planeCount) {
case 3:
m_buffer[bufferIndex].fd[2] = priv_handle->fd2;
m_buffer[bufferIndex].addr[2] = (char *)bufferAddr[2];
/* no break; */
case 2:
m_buffer[bufferIndex].fd[1] = priv_handle->fd1;
m_buffer[bufferIndex].addr[1] = (char *)bufferAddr[1];
/* no break; */
case 1:
m_buffer[bufferIndex].fd[0] = priv_handle->fd;
m_buffer[bufferIndex].addr[0] = (char *)bufferAddr[0];
break;
default:
android_printAssert(NULL, LOG_TAG, "ASSERT(%s[%d]):invalid m_buffer[%d].planeCount(%d) without metaPlane, assert!!!!",
__FUNCTION__, __LINE__, bufferIndex, m_buffer[bufferIndex].planeCount);
}
}
m_handleIsLocked[bufferIndex] = isLocked;
m_handle[bufferIndex] = bufHandle;
m_dequeuedBufCount++;
m_buffer[bufferIndex].status.position = EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL;
m_buffer[bufferIndex].status.permission = EXYNOS_CAMERA_BUFFER_PERMISSION_AVAILABLE;
#ifdef EXYNOS_CAMERA_BUFFER_TRACE
dump();
CLOGI("-- OUT -- m_dequeuedBufCount=%d, m_minUndequeuedBufCount=%d",
m_dequeuedBufCount, m_minUndequeuedBufCount);
CLOGD("Pre-dequeue buffer(%d)",
bufferIndex);
#endif
m_collectedBufferCount ++;
m_lock.unlock();
}
EXIT:
while ((m_collectedBufferCount >= (m_allowedMaxBufCount - m_minUndequeuedBufCount - BUFFER_COLLECT_MARGIN)
|| m_dequeuedBufCount >= (m_allowedMaxBufCount - m_minUndequeuedBufCount))
&& m_stopBufferCollector == false) {
usleep(BUFFER_COLLECTOR_WAITING_TIME);
}
return true;
}
status_t GrallocExynosCameraBufferManager::m_getCollectedBuffer(int *bufIndex)
{
status_t ret = NO_ERROR;
List<int>::iterator r;
int currentBufferIndex = -1;
if (m_collectedBufferCount < 1) {
CLOGE("Gralloc buffer collector has no Buffer");
ret = INVALID_OPERATION;
} else {
m_availableBufferIndexQLock.lock();
for (r = m_availableBufferIndexQ.begin(); r != m_availableBufferIndexQ.end(); r++) {
/* Found the collected buffer */
if (m_isCollectedBuffer(*r) == true) {
currentBufferIndex = *r;
break;
}
}
m_availableBufferIndexQLock.unlock();
}
if (currentBufferIndex > -1) {
*bufIndex = currentBufferIndex;
m_collectedBufferCount --;
CLOGV("Get buffer(%d) from gralloc buffer collector, available count(%d)",
currentBufferIndex, m_collectedBufferCount);
} else {
ret = INVALID_OPERATION;
CLOGE("Failed to get available gralloc buffer from buffer collector, available count(%d)",
m_collectedBufferCount);
}
return ret;
}
bool GrallocExynosCameraBufferManager::m_isCollectedBuffer(int bufferIndex)
{
bool ret = false;
bool isValidPosition = false;
bool isValidPermission = false;
switch (m_buffer[bufferIndex].status.position) {
case EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL:
isValidPosition = true;
break;
case EXYNOS_CAMERA_BUFFER_POSITION_NONE:
case EXYNOS_CAMERA_BUFFER_POSITION_IN_DRIVER:
case EXYNOS_CAMERA_BUFFER_POSITION_IN_SERVICE:
default:
isValidPosition = false;
break;
}
switch (m_buffer[bufferIndex].status.permission) {
case EXYNOS_CAMERA_BUFFER_PERMISSION_AVAILABLE:
isValidPermission = true;
break;
case EXYNOS_CAMERA_BUFFER_PERMISSION_NONE:
case EXYNOS_CAMERA_BUFFER_PERMISSION_IN_PROCESS:
default:
isValidPermission = false;
break;
}
ret = isValidPosition && isValidPermission;
return ret;
}
#endif /* USE_GRALLOC_BUFFER_COLLECTOR */
ExynosCameraFence::ExynosCameraFence()
{
m_fenceType = EXYNOS_CAMERA_FENCE_TYPE_BASE;
m_frameCount = -1;
m_index = -1;
m_acquireFence = -1;
m_releaseFence = -1;
m_fence = 0;
m_flagSwfence = false;
}
ExynosCameraFence::ExynosCameraFence(
enum EXYNOS_CAMERA_FENCE_TYPE fenceType,
int frameCount,
int index,
int acquireFence,
int releaseFence)
{
/* default setting */
m_fenceType = EXYNOS_CAMERA_FENCE_TYPE_BASE;
m_frameCount = -1;
m_index = -1;
m_acquireFence = -1;
m_releaseFence = -1;
m_fence = 0;
m_flagSwfence = false;
/* we will set from here */
if (fenceType <= EXYNOS_CAMERA_FENCE_TYPE_BASE ||
EXYNOS_CAMERA_FENCE_TYPE_MAX <= fenceType) {
CLOGE2("invalid fenceType(%d), frameCount(%d), index(%d)",
fenceType, frameCount, index);
return;
}
m_fenceType = fenceType;
m_frameCount = frameCount;
m_index = index;
m_acquireFence = acquireFence;
m_releaseFence = releaseFence;
if (0 <= m_acquireFence || 0 <= m_releaseFence) {
CLOGV2("fence(%d):m_acquireFence(%d), m_releaseFence(%d)",
m_frameCount, m_acquireFence, m_releaseFence);
}
#ifdef USE_SW_FENCE
m_flagSwfence = true;
#endif
if (m_flagSwfence == true) {
switch (m_fenceType) {
case EXYNOS_CAMERA_FENCE_TYPE_ACQUIRE:
m_fence = new Fence(acquireFence);
break;
case EXYNOS_CAMERA_FENCE_TYPE_RELEASE:
m_fence = new Fence(releaseFence);
break;
default:
CLOGE2("invalid m_fenceType(%d), m_frameCount(%d), m_index(%d)",
m_fenceType, m_frameCount, m_index);
break;
}
}
}
ExynosCameraFence::~ExynosCameraFence()
{
/* delete sp<Fence> addr */
m_fence = 0;
#ifdef FORCE_CLOSE_ACQUIRE_FD
static uint64_t closeCnt = 0;
if(m_acquireFence >= FORCE_CLOSE_ACQUIRE_FD_THRESHOLD) {
if(closeCnt++ % 1000 == 0) {
CLOGW2("Attempt to close acquireFence[%d], %ld th close.",
m_acquireFence, (long)closeCnt);
}
::close(m_acquireFence);
}
#endif
}
int ExynosCameraFence::getFenceType(void)
{
return m_fenceType;
}
int ExynosCameraFence::getFrameCount(void)
{
return m_frameCount;
}
int ExynosCameraFence::getIndex(void)
{
return m_index;
}
int ExynosCameraFence::getAcquireFence(void)
{
return m_acquireFence;
}
int ExynosCameraFence::getReleaseFence(void)
{
return m_releaseFence;
}
bool ExynosCameraFence::isValid(void)
{
bool ret = false;
if (m_flagSwfence == true) {
if (m_fence == NULL) {
CLOGE2("m_fence == NULL. so, fail");
ret = false;
} else {
ret = m_fence->isValid();
}
} else {
switch (m_fenceType) {
case EXYNOS_CAMERA_FENCE_TYPE_ACQUIRE:
if (0 <= m_acquireFence)
ret = true;
break;
case EXYNOS_CAMERA_FENCE_TYPE_RELEASE:
if (0 <= m_releaseFence)
ret = true;
break;
default:
CLOGE2("invalid m_fenceType(%d), m_frameCount(%d), m_index(%d)",
m_fenceType, m_frameCount, m_index);
break;
}
}
return ret;
}
status_t ExynosCameraFence::wait(int time)
{
status_t ret = NO_ERROR;
if (this->isValid() == false) {
CLOGE2("this->isValid() == false. so, fail!! frameCount(%d), index(%d), fencType(%d)",
m_frameCount, m_index, m_fenceType);
return INVALID_OPERATION;
}
if (m_flagSwfence == false) {
CLOGW2("m_flagSwfence == false. so, fail!! frameCount(%d), index(%d), fencType(%d)",
m_frameCount, m_index, m_fenceType);
return INVALID_OPERATION;
}
int waitTime = time;
if (waitTime < 0)
waitTime = 1000; /* wait 1 sec */
int fenceFd = -1;
switch (m_fenceType) {
case EXYNOS_CAMERA_FENCE_TYPE_ACQUIRE:
fenceFd = m_acquireFence;
break;
case EXYNOS_CAMERA_FENCE_TYPE_RELEASE:
fenceFd = m_releaseFence;
break;
default:
CLOGE2("invalid m_fenceType(%d), m_frameCount(%d), m_index(%d)",
m_fenceType, m_frameCount, m_index);
break;
}
ret = m_fence->wait(waitTime);
if (ret == TIMED_OUT) {
CLOGE2("Fence timeout. so, fail!! fenceFd(%d), frameCount(%d), index(%d), fencType(%d)",
fenceFd, m_frameCount, m_index, m_fenceType);
return INVALID_OPERATION;
} else if (ret != OK) {
CLOGE2("Fence wait error. so, fail!! fenceFd(%d), frameCount(%d), index(%d), fencType(%d)",
fenceFd, m_frameCount, m_index, m_fenceType);
return INVALID_OPERATION;
}
return ret;
}
ServiceExynosCameraBufferManager::ServiceExynosCameraBufferManager()
{
ExynosCameraBufferManager::init();
m_allocator = new ExynosCameraStreamAllocator();
CLOGD("");
for (int bufIndex = 0; bufIndex < VIDEO_MAX_FRAME; bufIndex++) {
m_handle[bufIndex] = NULL;
m_handleIsLocked[bufIndex] = false;
}
}
ServiceExynosCameraBufferManager::~ServiceExynosCameraBufferManager()
{
if (m_allocator != NULL) {
delete m_allocator;
m_allocator = NULL;
}
ExynosCameraBufferManager::deinit();
}
status_t ServiceExynosCameraBufferManager::registerBuffer(
int frameCount,
buffer_handle_t *handle,
int acquireFence,
int releaseFence,
enum EXYNOS_CAMERA_BUFFER_POSITION position)
{
EXYNOS_CAMERA_BUFFER_IN();
/*
* this->putBuffer(index, position) has same lock.
* so, don't lock here
*/
//Mutex::Autolock lock(m_lock);
status_t ret = NO_ERROR;
ExynosCameraFence *fence = NULL;
int index = -1;
ret = getIndexByHandle(handle, &index);
if (ret != NO_ERROR) {
CLOGE("getIndexByHandle error (%d)", ret);
goto func_exit;
}
ret = putBuffer(index, position);
if (ret != NO_ERROR) {
CLOGE("putBuffer(%d) error (%d)", index, ret);
goto func_exit;
}
m_lock.lock();
ret = m_registerBuffer(&handle, index);
if (ret < 0) {
CLOGE("m_setBuffer fail");
}
/*
* Wait release fence, before give buffer to h/w.
* Save acquire fence, this will give to h/w.
*/
fence = new ExynosCameraFence(
ExynosCameraFence::EXYNOS_CAMERA_FENCE_TYPE_ACQUIRE,
frameCount,
index,
acquireFence,
releaseFence);
m_pushFence(&m_fenceList, fence);
m_lock.unlock();
func_exit:
EXYNOS_CAMERA_BUFFER_OUT();
return ret;
}
status_t ServiceExynosCameraBufferManager::getIndexByHandle(buffer_handle_t *handle, int *index)
{
EXYNOS_CAMERA_BUFFER_IN();
status_t ret = OK;
int emptyIndex = -2;
int bufIndex = -2;
bool flag = false;
if (handle == NULL)
return BAD_VALUE;
if (m_indexOffset < 0 || VIDEO_MAX_FRAME < (m_reqBufCount + m_indexOffset)) {
CLOGE("abnormal value [m_indexOffset=%d, m_reqBufCount=%d]",
m_indexOffset, m_reqBufCount);
return BAD_VALUE;
}
for (int i = m_indexOffset; i < m_reqBufCount + m_indexOffset; i++) {
if (handle == m_handle[i]) {
emptyIndex = i;
CLOGV("index(%d), (%p/%p)", emptyIndex, handle , m_handle[i]);
flag = true;
break;
}
if (m_handle[i] == NULL) {
emptyIndex = i;
}
}
bufIndex = emptyIndex;
if (flag == false && bufIndex >= 0) {
CLOGD(" assigned new buffer handle(%p) Index(%d)", m_handle[bufIndex], bufIndex);
}
if ((bufIndex < 0) || (bufIndex >= m_allowedMaxBufCount + m_indexOffset)) {
CLOGE("Buffer index error (%d/%d)", bufIndex, m_allowedMaxBufCount);
return BAD_VALUE;
}
*index = bufIndex;
EXYNOS_CAMERA_BUFFER_OUT();
return ret;
}
status_t ServiceExynosCameraBufferManager::getHandleByIndex(buffer_handle_t **handle, int index)
{
EXYNOS_CAMERA_BUFFER_IN();
if ((index < 0) || (index >= m_allowedMaxBufCount)) {
CLOGE("Buffer index error (%d/%d)", index, m_allowedMaxBufCount);
return BAD_VALUE;
}
if (m_handle[index] == NULL)
CLOGE("m_handle[%d] is NULL!!", index);
*handle = m_handle[index];
EXYNOS_CAMERA_BUFFER_OUT();
return OK;
}
void ServiceExynosCameraBufferManager::m_resetSequenceQ()
{
Mutex::Autolock lock(m_availableBufferIndexQLock);
m_availableBufferIndexQ.clear();
/*
* service buffer is given by service.
* so, initial state is all un-available.
*/
/*
for (int bufIndex = 0; bufIndex < m_allocatedBufCount; bufIndex++)
m_availableBufferIndexQ.push_back(m_buffer[bufIndex].index);
*/
}
status_t ServiceExynosCameraBufferManager::m_setAllocator(void *allocator)
{
if (m_allocator == NULL) {
CLOGE("m_allocator equals NULL");
goto func_exit;
}
m_allocator->init((camera3_stream_t *)allocator);
func_exit:
return NO_ERROR;
}
status_t ServiceExynosCameraBufferManager::m_compareFdOfBufferHandle(const buffer_handle_t* handle, const ExynosCameraBuffer* exynosBuf) {
bool fdCmp = true;
const private_handle_t * privHandle = NULL;
int fdCmpPlaneNum = 0;
if (handle == NULL)
return BAD_VALUE;
if (exynosBuf == NULL)
return BAD_VALUE;
privHandle = private_handle_t::dynamicCast(*handle);
if (privHandle == NULL)
return BAD_VALUE;
fdCmpPlaneNum = (m_hasMetaPlane) ? exynosBuf->planeCount- 1 : exynosBuf->planeCount;
switch(fdCmpPlaneNum) {
/* Compare each plane's DMA fd */
case 3:
fdCmp = fdCmp && (exynosBuf->fd[2] == privHandle->fd2);
case 2:
fdCmp = fdCmp && (exynosBuf->fd[1] == privHandle->fd1);
case 1:
fdCmp = fdCmp && (exynosBuf->fd[0] == privHandle->fd);
break;
default:
CLOGE("Invalid plane count [m_buffer.planeCount=%d, m_hasMetaPlane=%d]",
exynosBuf->planeCount, m_hasMetaPlane);
return INVALID_OPERATION;
}
if(fdCmp == true) {
return NO_ERROR;
} else {
CLOGI(" same handle but different FD : index[%d] handleFd[%d/%d/%d] - bufFd[%d/%d/%d]"
, exynosBuf->index
, privHandle->fd, privHandle->fd1, privHandle->fd2
, exynosBuf->fd[0], exynosBuf->fd[1], exynosBuf->fd[2]);
return NAME_NOT_FOUND;
}
}
status_t ServiceExynosCameraBufferManager::m_registerBuffer(buffer_handle_t **handle, int index)
{
status_t ret = OK;
int planeCount = 0;
if (handle == NULL)
return BAD_VALUE;
const private_handle_t * privHandle = private_handle_t::dynamicCast(**handle);
CLOGV(" register handle[%d/%d/%d] - buf[index:%d][%d/%d/%d]"
, privHandle->fd, privHandle->fd1, privHandle->fd2
, index, m_buffer[index].fd[0], m_buffer[index].fd[1], m_buffer[index].fd[2]);
if (m_handleIsLocked[index] == true) {
/* Check the contents of buffer_handle_t */
if(m_compareFdOfBufferHandle(*handle, &m_buffer[index]) == NO_ERROR) {
return NO_ERROR;
}
/* Otherwise, DMA fd shoud be updated on following codes. */
}
m_handle[index] = *handle;
planeCount = m_buffer[index].planeCount;
if (m_hasMetaPlane == true)
planeCount--;
ret = m_allocator->lock(
handle,
m_buffer[index].fd,
m_buffer[index].addr,
&m_handleIsLocked[index], planeCount);
if (ret != 0)
CLOGE("m_allocator->lock failed.. ");
return ret;
}
status_t ServiceExynosCameraBufferManager::m_alloc(int bIndex, int eIndex)
{
EXYNOS_CAMERA_BUFFER_IN();
status_t ret = OK;
CLOGD("");
for (int bufIndex = bIndex; bufIndex < eIndex; bufIndex++) {
if (updateStatus(
bufIndex,
0,
EXYNOS_CAMERA_BUFFER_POSITION_IN_SERVICE,
EXYNOS_CAMERA_BUFFER_PERMISSION_NONE) != NO_ERROR) {
CLOGE("setStatus failed [bufIndex=%d, position=SERVICE, permission=NONE]",
bufIndex);
ret = INVALID_OPERATION;
break;
}
}
/*
* service buffer is given by service.
* so, initial state is all un-available.
*/
m_availableBufferIndexQLock.lock();
m_availableBufferIndexQ.clear();
m_availableBufferIndexQLock.unlock();
EXYNOS_CAMERA_BUFFER_OUT();
return ret;
}
status_t ServiceExynosCameraBufferManager::m_free(int bIndex, int eIndex)
{
EXYNOS_CAMERA_BUFFER_IN();
status_t ret = NO_ERROR;
CLOGD("IN");
dump();
for (int bufIndex = bIndex; bufIndex < eIndex; bufIndex++) {
if (m_handleIsLocked[bufIndex] == false) {
CLOGD("buffer [bufIndex=%d] already free", bufIndex);
continue;
}
m_removeFence(&m_fenceList, bufIndex);
m_handle[bufIndex] = NULL;
m_handleIsLocked[bufIndex] = false;
if (updateStatus(
bufIndex,
0,
EXYNOS_CAMERA_BUFFER_POSITION_NONE,
EXYNOS_CAMERA_BUFFER_PERMISSION_NONE) != NO_ERROR) {
CLOGE("setStatus failed [bIndex=%d, position=NONE, permission=NONE]",
bufIndex);
ret = INVALID_OPERATION;
goto func_exit;
}
if (m_graphicBufferAllocator.free(bufIndex) != NO_ERROR) {
CLOGE("m_graphicBufferAllocator.free(%d) fail",
bufIndex);
ret = INVALID_OPERATION;
goto func_exit;
}
}
func_exit:
EXYNOS_CAMERA_BUFFER_OUT();
return ret;
}
status_t ServiceExynosCameraBufferManager::m_increase(__unused int increaseCount)
{
CLOGD("allocMode(%d) is invalid. Do nothing", m_allocMode);
return INVALID_OPERATION;
}
status_t ServiceExynosCameraBufferManager::m_decrease(void)
{
return INVALID_OPERATION;
}
status_t ServiceExynosCameraBufferManager::m_putBuffer(__unused int bufIndex)
{
EXYNOS_CAMERA_BUFFER_IN();
status_t ret = NO_ERROR;
CLOGV("no effect" );
EXYNOS_CAMERA_BUFFER_OUT();
return ret;
}
status_t ServiceExynosCameraBufferManager::m_getBuffer(int *bufIndex, int *acquireFence, int *releaseFence)
{
EXYNOS_CAMERA_BUFFER_IN();
status_t ret = NO_ERROR;
ExynosCameraFence *ptrFence = NULL;
int frameCount = -1;
/* this is default value */
*acquireFence = -1;
*releaseFence = -1;
ptrFence = m_popFence(&m_fenceList);
if (ptrFence == NULL) {
CLOGE("m_popFence() fail");
ret = INVALID_OPERATION;
goto done;
}
*bufIndex = ptrFence->getIndex();
if (*bufIndex < 0) {
CLOGE("*bufIndex(%d) < 0", *bufIndex);
ret = BAD_VALUE;
goto done;
}
frameCount = ptrFence->getFrameCount();
if (frameCount < 0) {
CLOGE("frameCount(%d) < 0", frameCount);
ret = BAD_VALUE;
goto done;
}
#ifdef USE_CAMERA2_USE_FENCE
if (ptrFence != NULL && ret == NO_ERROR) {
#ifdef USE_SW_FENCE
/* wait before give buffer to hardware */
if (ptrFence->isValid() == true) {
ret = m_waitFence(ptrFence);
if (ret != NO_ERROR) {
CLOGE("m_waitFence() fail");
goto done;
}
} else {
CLOGV("Fence is invalid. framecount=%d", frameCount);
}
#else
/* give fence to H/W */
*acquireFence = ptrFence->getAcquireFence();
*releaseFence = ptrFence->getReleaseFence();
#endif
}
#endif
if (m_allocator->unlock(m_handle[*bufIndex]) != 0) {
CLOGE("grallocHal->unlock failed");
return INVALID_OPERATION;
}
done:
if (ptrFence != NULL) {
delete ptrFence;
ptrFence = NULL;
}
EXYNOS_CAMERA_BUFFER_OUT();
return ret;
}
status_t ServiceExynosCameraBufferManager::m_waitFence(ExynosCameraFence *fence)
{
status_t ret = NO_ERROR;
#if 0
/* reference code */
sp<Fence> bufferAcquireFence = new Fence(buffer->acquire_fence);
ret = bufferAcquireFence->wait(1000); /* 1 sec */
if (ret == TIMED_OUT) {
CLOGE("Fence timeout(%d)!!", request->frame_number);
return INVALID_OPERATION;
} else if (ret != OK) {
CLOGE("Waiting on Fence error(%d)!!", request->frame_number);
return INVALID_OPERATION;
}
#endif
if (fence == NULL) {
CLOGE("fence == NULL. so, fail");
return INVALID_OPERATION;
}
if (fence->isValid() == false) {
CLOGE("fence(%d)->isValid() == false. so, fail",
fence->getFrameCount());
return INVALID_OPERATION;
}
CLOGV("Valid fence on frameCount(%d)",
fence->getFrameCount());
ret = fence->wait();
if (ret != NO_ERROR) {
CLOGE("fence(frameCount : %d)->wait() fail",
fence->getFrameCount());
return INVALID_OPERATION;
} else {
CLOGV("fence(frameCount : %d)->wait() succeed",
fence->getFrameCount());
}
return ret;
}
void ServiceExynosCameraBufferManager::m_pushFence(List<ExynosCameraFence *> *list, ExynosCameraFence *fence)
{
Mutex::Autolock l(m_fenceListLock);
list->push_back(fence);
}
ExynosCameraFence *ServiceExynosCameraBufferManager::m_popFence(List<ExynosCameraFence *> *list)
{
ExynosCameraFence *curFence = NULL;
List<ExynosCameraFence *>::iterator r;
Mutex::Autolock l(m_fenceListLock);
if (list->empty()) {
CLOGE("list is empty");
return NULL;
}
r = list->begin()++;
curFence = *r;
list->erase(r);
return curFence;
}
status_t ServiceExynosCameraBufferManager::m_removeFence(List<ExynosCameraFence *> *list, int index)
{
ExynosCameraFence *curFence = NULL;
List<ExynosCameraFence *>::iterator r;
Mutex::Autolock l(m_fenceListLock);
if (list->empty()) {
CLOGD("list is empty");
return NO_ERROR;
}
r = list->begin()++;
do {
curFence = *r;
if (curFence == NULL) {
CLOGE("curFence is empty");
return INVALID_OPERATION;
}
if (curFence->getIndex() == index) {
CLOGV("remove Fence(%d), frameCount(%d)",
index, curFence->getFrameCount());
list->erase(r);
delete curFence;
curFence = NULL;
return NO_ERROR;
}
r++;
} while (r != list->end());
CLOGD("Cannot find index(%d)", index);
return INVALID_OPERATION;
}
} // namespace android