| /* |
| * Copyright 2017, 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_SERVICE_GRALLOC_TYPE: |
| return (ExynosCameraBufferManager *)new ServiceExynosCameraBufferManager(-1); |
| 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; |
| |
| setCameraId(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; |
| 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; |
| |
| 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 " |
| "(m_allocatedBufCount=%d, m_reqBufCount=%d, m_allowedMaxBufCount=%d) --- dumpBufferInfo ---", |
| m_allocatedBufCount, m_reqBufCount, m_allowedMaxBufCount); |
| dumpBufferInfo(); |
| CLOGD("------------------------------------------------------------------"); |
| |
| 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(); |
| CLOGD("------------------------------------------------------"); |
| |
| 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(buffer_manager_configuration_t info) |
| { |
| 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 = info.startBufIndex; |
| |
| if (info.allowedMaxBufCount < info.reqBufCount) { |
| CLOGW("abnormal value [reqBufCount=%d, allowedMaxBufCount=%d]", |
| info.reqBufCount, info.allowedMaxBufCount); |
| info.allowedMaxBufCount = info.reqBufCount; |
| } |
| |
| if (info.reqBufCount < 0 || VIDEO_MAX_FRAME < info.reqBufCount) { |
| CLOGE("abnormal value [reqBufCount=%d]", info.reqBufCount); |
| ret = BAD_VALUE; |
| goto func_exit; |
| } |
| |
| if (info.planeCount < 0 || EXYNOS_CAMERA_BUFFER_MAX_PLANES <= info.planeCount) { |
| CLOGE("abnormal value [planeCount=%d]", info.planeCount); |
| ret = BAD_VALUE; |
| goto func_exit; |
| } |
| |
| totalPlaneCount = m_getTotalPlaneCount(info.planeCount, info.batchSize, info.createMetaPlane); |
| if (totalPlaneCount < 1 || EXYNOS_CAMERA_BUFFER_MAX_PLANES < totalPlaneCount) { |
| CLOGE("Failed to getTotalPlaneCount." \ |
| "totalPlaneCount %d planeCount %d batchSize %d hasMetaPlane %d", |
| totalPlaneCount, info.planeCount, info.batchSize, info.createMetaPlane); |
| ret = INVALID_OPERATION; |
| goto func_exit; |
| } |
| |
| if (info.createMetaPlane == true) { |
| info.size[info.planeCount - 1] = EXYNOS_CAMERA_META_PLANE_SIZE; |
| m_hasMetaPlane = true; |
| } |
| |
| for (int bufIndex = m_indexOffset; bufIndex < info.allowedMaxBufCount + m_indexOffset; bufIndex++) { |
| for (int planeIndex = 0; planeIndex < info.planeCount; planeIndex++) { |
| if (info.size[planeIndex] <= 0) { |
| CLOGE("abnormal value [size=%d, planeIndex %d]", |
| info.size[planeIndex], planeIndex); |
| ret = BAD_VALUE; |
| goto func_exit; |
| } |
| |
| int curPlaneIndex = ((info.createMetaPlane == true && planeIndex == info.planeCount -1) ? |
| (totalPlaneCount - 1) : planeIndex); |
| |
| m_buffer[bufIndex].size[curPlaneIndex] = info.size[planeIndex]; |
| m_buffer[bufIndex].bytesPerLine[curPlaneIndex] = info.bytesPerLine[planeIndex]; |
| } |
| |
| /* Copy image plane imformation into other planes in batch buffer */ |
| if (info.batchSize > 1) { |
| int imagePlaneCount = (m_hasMetaPlane == true) ? (info.planeCount - 1) : info.planeCount; |
| for (int batchIndex = 1; batchIndex < info.batchSize; batchIndex++) { |
| for (int planeIndex = 0; planeIndex < imagePlaneCount; planeIndex++) { |
| int curPlaneIndex = (batchIndex * imagePlaneCount) + planeIndex; |
| m_buffer[bufIndex].size[curPlaneIndex] = info.size[planeIndex]; |
| m_buffer[bufIndex].bytesPerLine[curPlaneIndex] = info.bytesPerLine[planeIndex]; |
| } |
| } |
| } |
| |
| m_buffer[bufIndex].planeCount = info.planeCount; |
| m_buffer[bufIndex].type = info.type; |
| m_buffer[bufIndex].batchSize = info.batchSize; |
| } |
| |
| m_allowedMaxBufCount = info.allowedMaxBufCount + info.startBufIndex; |
| m_reqBufCount = info.reqBufCount; |
| m_flagNeedMmap = info.needMmap; |
| m_allocMode = info.allocMode; |
| m_reservedMemoryCount = info.reservedMemoryCount; |
| func_exit: |
| |
| EXYNOS_CAMERA_BUFFER_OUT(); |
| |
| 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::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; |
| |
| 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; |
| } |
| |
| 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 (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; |
| |
| bufferIndex = *reqBufIndex; |
| permission = EXYNOS_CAMERA_BUFFER_PERMISSION_NONE; |
| |
| if (m_allocatedBufCount == 0) { |
| CLOGE("m_allocatedBufCount equals zero"); |
| 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; |
| *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; |
| } |
| |
| status_t ExynosCameraBufferManager::cancelBuffer(int bufIndex) |
| { |
| return putBuffer(bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_NONE); |
| } |
| |
| 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::getIndexByFd(int fd, int *index) |
| { |
| if (fd < 0) { |
| CLOGE("Invalid FD %d", fd); |
| return BAD_VALUE; |
| } |
| |
| *index = -1; |
| for (int bufIndex = m_indexOffset; bufIndex < m_reqBufCount + m_indexOffset; bufIndex++) { |
| if (m_buffer[bufIndex].fd[0] == 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; |
| |
| 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 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_buffer[bufIndex].getMetaPlaneIndex(); |
| 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; |
| 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) { |
| 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; |
| 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]; |
| } |
| } |
| |
| if (isMetaPlane == false) { |
| timer.stop(); |
| durationTime = timer.durationMsecs(); |
| durationTimeSum += durationTime; |
| CLOGD("duration time(%5d msec):(type=%d, bufIndex=%d, size=%.2f, batchSize=%d)", |
| (int)durationTime, m_buffer[bufIndex].type, bufIndex, |
| (float)bufferSize / (float)(1024 * 1024), m_buffer[bufIndex].batchSize); |
| |
| 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_buffer[bufIndex].getMetaPlaneIndex(); |
| } |
| |
| 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; |
| } |
| } |
| |
| 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; |
| } |
| } |
| |
| 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("Invalid values. planeCount %d batchSize %d", planeCount, batchSize); |
| return 0; |
| } |
| |
| int totalPlaneCount = 0; |
| if (hasMetaPlane == true) { |
| int imagePlaneCount = planeCount - 1; |
| totalPlaneCount = (imagePlaneCount * batchSize) + 1; |
| } else { |
| totalPlaneCount = planeCount * batchSize; |
| } |
| |
| return totalPlaneCount; |
| } |
| |
| 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; |
| } |
| |
| void ExynosCameraBufferManager::printBufferState(void) |
| { |
| for (int i = m_indexOffset; i < m_allocatedBufCount + m_indexOffset; i++) { |
| CLOGV("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( |
| __unused const char *funcName, |
| __unused 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) |
| { |
| #ifdef EXYNOS_CAMERA_DUMP_BUFFER_INFO |
| 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(); |
| #endif |
| |
| 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) |
| { |
| status_t ret = NO_ERROR; |
| |
| ret = m_defaultAlloc(bIndex, eIndex, false); |
| if (ret != NO_ERROR) { |
| CLOGE("Failed to alloc. bIndex %d eIndex %d ret %d", |
| bIndex, eIndex, ret); |
| return ret; |
| } |
| |
| if (m_buffer[0].batchSize > 1) { |
| ret = m_constructBufferContainer(bIndex, eIndex); |
| if (ret != NO_ERROR) { |
| CLOGE("Failed to constructBufferContainer. bIndex %d eIndex %d ret %d", |
| bIndex, eIndex, ret); |
| return ret; |
| } |
| } |
| |
| return NO_ERROR; |
| } |
| |
| status_t InternalExynosCameraBufferManager::m_free(int bIndex, int eIndex) |
| { |
| status_t ret = NO_ERROR; |
| |
| if (m_buffer[0].batchSize > 1) { |
| ret = m_destructBufferContainer(bIndex, eIndex); |
| if (ret != NO_ERROR) { |
| CLOGE("Failed to destructBufferContainer. bIndex %d eIndex %d ret %d", |
| bIndex, eIndex, ret); |
| return ret; |
| } |
| } else { |
| ret = m_defaultFree(bIndex, eIndex, false); |
| if (ret != NO_ERROR) { |
| CLOGE("Failed to free. bIndex %d eIndex %d ret %d", |
| bIndex, eIndex, ret); |
| return ret; |
| } |
| } |
| |
| return NO_ERROR; |
| } |
| |
| 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_constructBufferContainer(int bIndex, int eIndex) |
| { |
| EXYNOS_CAMERA_BUFFER_IN(); |
| |
| status_t ret = NO_ERROR; |
| ExynosCameraDurationTimer timer; |
| |
| if (m_defaultAllocator == NULL) { |
| CLOGE("defaultAllocator is NULL"); |
| ret = INVALID_OPERATION; |
| goto func_exit; |
| } |
| |
| if (bIndex < 0 || eIndex < 0) { |
| CLOGE("Invalid parameters. bIndex %d eIndex %d", |
| bIndex, eIndex); |
| ret = BAD_VALUE; |
| goto func_exit; |
| } |
| |
| for (int bufIndex = bIndex; bufIndex < eIndex; bufIndex++) { |
| /* Get buffer container FD for same size planes */ |
| int imagePlaneCount = (m_hasMetaPlane == true) ? |
| (m_buffer[bufIndex].planeCount - 1) |
| : m_buffer[bufIndex].planeCount; |
| |
| timer.start(); |
| for (int planeIndex = 0; planeIndex < imagePlaneCount; planeIndex++) { |
| /* Gather single FDs */ |
| int fds[EXYNOS_CAMERA_BUFFER_MAX_PLANES]; |
| for (int batchIndex = 0; batchIndex < m_buffer[bufIndex].batchSize; batchIndex++) { |
| fds[batchIndex] = m_buffer[bufIndex].fd[(batchIndex * imagePlaneCount) + planeIndex]; |
| } |
| |
| ret = m_defaultAllocator->createBufferContainer(fds, |
| m_buffer[bufIndex].batchSize, |
| &m_buffer[bufIndex].containerFd[planeIndex]); |
| if (ret != NO_ERROR) { |
| CLOGE("[B%d P%d]Failed to createBufferContainer. batchSize %d ret %d", |
| bufIndex, planeIndex, m_buffer[bufIndex].batchSize, ret); |
| ret = INVALID_OPERATION; |
| goto func_exit; |
| } |
| |
| /* Release single buffer FD. |
| * Buffer container will have reference for each single buffer. |
| */ |
| for (int batchIndex = 0; batchIndex < m_buffer[bufIndex].batchSize; batchIndex++) { |
| int curPlaneIndex = (batchIndex * imagePlaneCount) + planeIndex; |
| ret = m_defaultAllocator->free(m_buffer[bufIndex].size[curPlaneIndex], |
| &(m_buffer[bufIndex].fd[curPlaneIndex]), |
| &(m_buffer[bufIndex].addr[curPlaneIndex]), |
| m_flagNeedMmap); |
| if (ret != NO_ERROR) { |
| CLOGE("[B%d P%d FD%d]Failed to free. ret %d", |
| bufIndex, planeIndex, m_buffer[bufIndex].fd[curPlaneIndex], ret); |
| /* continue */ |
| } |
| } |
| } |
| |
| timer.stop(); |
| CLOGD("duration time(%5d msec):(bufIndex=%d, batchSize=%d, fd=%d/%d/%d)", |
| (int)timer.durationMsecs(), bufIndex, m_buffer[bufIndex].batchSize, |
| m_buffer[bufIndex].containerFd[0], m_buffer[bufIndex].containerFd[1], m_buffer[bufIndex].containerFd[2]); |
| } |
| |
| func_exit: |
| EXYNOS_CAMERA_BUFFER_OUT(); |
| |
| return ret; |
| } |
| |
| status_t InternalExynosCameraBufferManager::m_destructBufferContainer(int bIndex, int eIndex) |
| { |
| EXYNOS_CAMERA_BUFFER_IN(); |
| |
| status_t ret = NO_ERROR; |
| char *dummyAddr = NULL; |
| |
| if (m_defaultAllocator == NULL) { |
| CLOGE("defaultAllocator is NULL"); |
| ret = INVALID_OPERATION; |
| goto func_exit; |
| } |
| |
| if (bIndex < 0 || eIndex < 0) { |
| CLOGE("Invalid parameters. bIndex %d eIndex %d", |
| bIndex, eIndex); |
| ret = BAD_VALUE; |
| goto func_exit; |
| } |
| |
| for (int bufIndex = bIndex; bufIndex < eIndex; bufIndex++) { |
| int imagePlaneCount = (m_hasMetaPlane == true) ? |
| (m_buffer[bufIndex].planeCount - 1) |
| : m_buffer[bufIndex].planeCount; |
| |
| for (int planeIndex = 0; planeIndex < imagePlaneCount; planeIndex++) { |
| ret = m_defaultAllocator->free(m_buffer[bufIndex].size[planeIndex], |
| &(m_buffer[bufIndex].containerFd[planeIndex]), |
| &dummyAddr, /*mapNeeded */false); |
| if (ret != NO_ERROR) { |
| CLOGE("[B%d P%d FD%d]Failed to free containerFd. ret %d", |
| bufIndex, planeIndex, m_buffer[bufIndex].containerFd[planeIndex], ret); |
| /* continue */ |
| } |
| } |
| } |
| |
| func_exit: |
| EXYNOS_CAMERA_BUFFER_OUT(); |
| |
| return ret; |
| } |
| |
| 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); |
| } |
| |
| return ret; |
| } |
| |
| ExynosCameraFence::ExynosCameraFence() |
| { |
| m_fenceType = EXYNOS_CAMERA_FENCE_TYPE_BASE; |
| |
| m_acquireFence = -1; |
| m_releaseFence = -1; |
| |
| m_fence = 0; |
| |
| m_flagSwfence = false; |
| } |
| |
| ExynosCameraFence::ExynosCameraFence( |
| enum EXYNOS_CAMERA_FENCE_TYPE fenceType, |
| int acquireFence, |
| int releaseFence) |
| { |
| /* default setting */ |
| m_fenceType = EXYNOS_CAMERA_FENCE_TYPE_BASE; |
| 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) { |
| ALOGE("ERR(%s[%d]):Invalid fenceType(%d)", |
| __FUNCTION__, __LINE__, fenceType); |
| return; |
| } |
| |
| m_fenceType = fenceType; |
| m_acquireFence = acquireFence; |
| m_releaseFence = releaseFence; |
| |
| if (0 <= m_acquireFence || 0 <= m_releaseFence) { |
| ALOGV("DEBUG(%s[%d]):m_acquireFence(%d), m_releaseFence(%d)", |
| __FUNCTION__, __LINE__, 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: |
| ALOGE("ERR(%s[%d]):invalid m_fenceType(%d)", |
| __FUNCTION__, __LINE__, m_fenceType); |
| break; |
| } |
| } |
| } |
| |
| ExynosCameraFence::~ExynosCameraFence() |
| { |
| /* delete sp<Fence> addr */ |
| m_fence = 0; |
| static uint64_t closeCnt = 0; |
| if(m_acquireFence >= ACQUIRE_FD_THRESHOLD) { |
| if (closeCnt++ % 1000 == 0) { |
| CLOGW2("Attempt to close acquireFence[%d], %ld th close.", |
| m_acquireFence, (long)closeCnt); |
| } |
| } |
| } |
| |
| int ExynosCameraFence::getFenceType(void) |
| { |
| return m_fenceType; |
| } |
| |
| 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_fenceType); |
| break; |
| } |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraFence::wait(int time) |
| { |
| status_t ret = NO_ERROR; |
| |
| if (this->isValid() == false) { |
| CLOGE2("this->isValid() == false. so, fail!! fencType(%d)", |
| m_fenceType); |
| return INVALID_OPERATION; |
| } |
| |
| if (m_flagSwfence == false) { |
| CLOGW2("m_flagSwfence == false. so, fail!! fencType(%d)", |
| 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_fenceType); |
| break; |
| } |
| |
| ret = m_fence->wait(waitTime); |
| if (ret == TIMED_OUT) { |
| CLOGE2("Fence timeout. so, fail!! fenceFd(%d), fencType(%d)", |
| fenceFd, m_fenceType); |
| |
| return INVALID_OPERATION; |
| } else if (ret != OK) { |
| CLOGE2("Fence wait error. so, fail!! fenceFd(%d), fencType(%d)", |
| fenceFd, m_fenceType); |
| |
| return INVALID_OPERATION; |
| } |
| |
| return ret; |
| } |
| |
| ServiceExynosCameraBufferManager::ServiceExynosCameraBufferManager(int actualFormat) |
| { |
| ExynosCameraBufferManager::init(); |
| |
| m_allocator = new ExynosCameraStreamAllocator(actualFormat); |
| |
| 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::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; |
| int totalPlaneCount = 0; |
| enum EXYNOS_CAMERA_BUFFER_PERMISSION permission; |
| |
| 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; |
| } |
| |
| 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; |
| } |
| |
| /* Clear Image Plane Information */ |
| totalPlaneCount = m_getTotalPlaneCount(m_buffer[bufIndex].planeCount, |
| m_buffer[bufIndex].batchSize, |
| m_hasMetaPlane); |
| totalPlaneCount -= (m_hasMetaPlane == true)? 1 : 0; |
| |
| for (int i = 0; i < totalPlaneCount; i++) { |
| m_buffer[bufIndex].fd[i] = -1; |
| m_buffer[bufIndex].addr[i] = NULL; |
| m_buffer[bufIndex].handle[i] = NULL; |
| m_buffer[bufIndex].acquireFence[i] = -1; |
| m_buffer[bufIndex].releaseFence[i] = -1; |
| } |
| |
| if (m_buffer[bufIndex].batchSize > 1) { |
| ret = m_destructBufferContainer(bufIndex); |
| if (ret != NO_ERROR) { |
| CLOGE("[B%d]Failed to destructBufferContainer. ret %d", bufIndex, ret); |
| /* continue */ |
| } |
| } |
| |
| 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; |
| } |
| |
| status_t ServiceExynosCameraBufferManager::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; |
| int planeCount; |
| enum EXYNOS_CAMERA_BUFFER_PERMISSION permission; |
| ExynosCameraFence* fence = NULL; |
| |
| bufferIndex = *reqBufIndex; |
| permission = EXYNOS_CAMERA_BUFFER_PERMISSION_NONE; |
| |
| if (m_allocatedBufCount == 0) { |
| CLOGE("m_allocatedBufCount equals zero"); |
| 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 { |
| 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; |
| |
| for (int batchIndex = 0; batchIndex < m_buffer[bufferIndex].batchSize; batchIndex++) { |
| if (buffer->handle[batchIndex] == NULL) { |
| CLOGW("[B%d-%d]Handle is NULL. Skip it", bufferIndex, batchIndex); |
| continue; |
| } |
| |
| fence = new ExynosCameraFence( |
| ExynosCameraFence::EXYNOS_CAMERA_FENCE_TYPE_ACQUIRE, |
| buffer->acquireFence[batchIndex], |
| buffer->releaseFence[batchIndex]); |
| |
| /* Wait fence */ |
| #ifdef USE_CAMERA2_USE_FENCE |
| if (fence != NULL) { |
| #ifdef USE_SW_FENCE |
| /* wait before give buffer to hardware */ |
| if (fence->isValid() == true) { |
| ret = m_waitFence(fence); |
| if (ret != NO_ERROR) { |
| CLOGE("[B%d-%d]m_waitFence() fail", bufferIndex, batchIndex); |
| goto loop_continue; |
| } |
| } else { |
| CLOGV("[B%d-%d]Fence is invalid", bufferIndex, batchIndex); |
| } |
| /* Initialize fence */ |
| buffer->acquireFence[batchIndex] = -1; |
| buffer->releaseFence[batchIndex] = -1; |
| #else |
| /* give fence to H/W */ |
| buffer->acquireFence[batchIndex] = ptrFence->getAcquireFence(); |
| buffer->releaseFence[batchIndex] = ptrFence->getReleaseFence(); |
| #endif |
| } |
| #endif |
| |
| planeCount = (m_hasMetaPlane == true) ? m_buffer[bufferIndex].planeCount - 1 |
| : m_buffer[bufferIndex].planeCount; |
| |
| if (m_flagNeedMmap == true) { |
| /* Get FD/VA from handle */ |
| ret = m_allocator->lock( |
| &(buffer->handle[batchIndex]), |
| &(m_buffer[bufferIndex].fd[batchIndex * planeCount]), |
| &(m_buffer[bufferIndex].addr[batchIndex * planeCount]), |
| &m_handleIsLocked[bufferIndex], |
| planeCount); |
| if (ret != NO_ERROR) { |
| CLOGE("[B%d]Failed to grallocHal->lock buffer_handle", bufferIndex); |
| goto loop_continue; |
| } |
| |
| /* Sync cache operation */ |
| ret = m_allocator->unlock(buffer->handle[batchIndex]); |
| if (ret != NO_ERROR) { |
| CLOGE("[B%d]Failed to grallocHal->unlock buffer_handle", bufferIndex); |
| goto loop_continue; |
| } |
| } else { |
| /* Get FD from handle */ |
| ret = m_getBufferInfoFromHandle(*(buffer->handle[batchIndex]), |
| planeCount, |
| &(m_buffer[bufferIndex].fd[batchIndex * planeCount])); |
| if (ret != NO_ERROR) { |
| CLOGE("[B%d]Failed to getBufferInfoFromHandle. ret %d", bufferIndex, ret); |
| goto loop_continue; |
| } |
| } |
| |
| m_buffer[bufferIndex].handle[batchIndex] = buffer->handle[batchIndex]; |
| m_handleIsLocked[bufferIndex] = false; |
| |
| loop_continue: |
| if (fence != NULL) { |
| delete fence; |
| fence = NULL; |
| } |
| } |
| |
| if (m_buffer[bufferIndex].batchSize > 1) { |
| ret = m_constructBufferContainer(bufferIndex); |
| if (ret != NO_ERROR) { |
| CLOGE("[B%d]Failed to constructBufferContainer. ret %d", bufferIndex, ret); |
| /* continue */ |
| } |
| } |
| |
| *reqBufIndex = bufferIndex; |
| *buffer = m_buffer[bufferIndex]; |
| |
| func_exit: |
| |
| EXYNOS_CAMERA_BUFFER_OUT(); |
| |
| return ret; |
| } |
| |
| 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_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) { |
| CLOGV("buffer [bufIndex=%d] already free", bufIndex); |
| continue; |
| } |
| |
| 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; |
| } |
| } |
| |
| 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_getBufferInfoFromHandle(buffer_handle_t handle, |
| int planeCount, |
| int fd[]) |
| { |
| int curPlaneCount = planeCount; |
| |
| if (handle->version != sizeof(native_handle_t)) { |
| android_printAssert(NULL, LOG_TAG, |
| "ASSERT(%s):native_handle_t size mismatch. local %d != framework %d", |
| __FUNCTION__, (int)sizeof(native_handle_t), handle->version); |
| |
| return BAD_VALUE; |
| } |
| |
| if (handle->numFds != planeCount) { |
| curPlaneCount = (handle->numFds < planeCount)? handle->numFds : planeCount; |
| CLOGW("planeCount mismatch. local %d != handle %d. Use %d.", |
| planeCount, handle->numFds, curPlaneCount); |
| } |
| |
| for (int i = 0; i < curPlaneCount; i++) { |
| if (handle->data[i] < 0) { |
| CLOGE("Invalid FD %d for plane %d", |
| handle->data[i], i); |
| continue; |
| } |
| |
| fd[i] = handle->data[i]; |
| } |
| |
| return NO_ERROR; |
| } |
| |
| 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->isValid() == false. so, fail"); |
| return INVALID_OPERATION; |
| } |
| |
| CLOGV("Valid fence"); |
| |
| |
| ret = fence->wait(); |
| if (ret != NO_ERROR) { |
| CLOGE("fence->wait() fail"); |
| return INVALID_OPERATION; |
| } else { |
| CLOGV("fence->wait() succeed"); |
| } |
| |
| return ret; |
| } |
| |
| status_t ServiceExynosCameraBufferManager::m_constructBufferContainer(int bufIndex) |
| { |
| EXYNOS_CAMERA_BUFFER_IN(); |
| |
| status_t ret = NO_ERROR; |
| ExynosCameraDurationTimer timer; |
| int imagePlaneCount = 0; |
| |
| if (m_defaultAllocator == NULL) { |
| CLOGE("defaultAllocator is NULL"); |
| ret = INVALID_OPERATION; |
| goto func_exit; |
| } |
| |
| if (bufIndex < 0) { |
| CLOGE("Invalid parameters. bufIndex %d", bufIndex); |
| ret = BAD_VALUE; |
| goto func_exit; |
| } |
| |
| /* Get buffer container FD for same size planes */ |
| imagePlaneCount = (m_hasMetaPlane == true) ? (m_buffer[bufIndex].planeCount - 1) |
| : m_buffer[bufIndex].planeCount; |
| |
| timer.start(); |
| for (int planeIndex = 0; planeIndex < imagePlaneCount; planeIndex++) { |
| /* Gather single FDs */ |
| int fds[EXYNOS_CAMERA_BUFFER_MAX_PLANES]; |
| for (int batchIndex = 0; batchIndex < m_buffer[bufIndex].batchSize; batchIndex++) { |
| fds[batchIndex] = m_buffer[bufIndex].fd[(batchIndex * imagePlaneCount) + planeIndex]; |
| } |
| |
| ret = m_defaultAllocator->createBufferContainer(fds, |
| m_buffer[bufIndex].batchSize, |
| &m_buffer[bufIndex].containerFd[planeIndex]); |
| if (ret != NO_ERROR) { |
| CLOGE("[B%d P%d]Failed to createBufferContainer. batchSize %d ret %d", |
| bufIndex, planeIndex, m_buffer[bufIndex].batchSize, ret); |
| ret = INVALID_OPERATION; |
| goto func_exit; |
| } |
| } |
| |
| timer.stop(); |
| CLOGV("duration time(%5d msec):(bufIndex=%d, batchSize=%d, fd=%d/%d/%d)", |
| (int)timer.durationMsecs(), bufIndex, m_buffer[bufIndex].batchSize, |
| m_buffer[bufIndex].containerFd[0], m_buffer[bufIndex].containerFd[1], m_buffer[bufIndex].containerFd[2]); |
| |
| func_exit: |
| EXYNOS_CAMERA_BUFFER_OUT(); |
| |
| return ret; |
| } |
| |
| status_t ServiceExynosCameraBufferManager::m_destructBufferContainer(int bufIndex) |
| { |
| EXYNOS_CAMERA_BUFFER_IN(); |
| |
| status_t ret = NO_ERROR; |
| int imagePlaneCount = 0; |
| char* dummyAddr = NULL; |
| |
| if (m_defaultAllocator == NULL) { |
| CLOGE("defaultAllocator is NULL"); |
| ret = INVALID_OPERATION; |
| goto func_exit; |
| } |
| |
| if (bufIndex < 0) { |
| CLOGE("Invalid parameters. bufIndex %d", bufIndex); |
| ret = BAD_VALUE; |
| goto func_exit; |
| } |
| |
| imagePlaneCount = (m_hasMetaPlane == true) ? (m_buffer[bufIndex].planeCount - 1) |
| : m_buffer[bufIndex].planeCount; |
| |
| for (int planeIndex = 0; planeIndex < imagePlaneCount; planeIndex++) { |
| ret = m_defaultAllocator->free(m_buffer[bufIndex].size[planeIndex], |
| &(m_buffer[bufIndex].containerFd[planeIndex]), |
| &dummyAddr, /*mapNeeded */false); |
| if (ret != NO_ERROR) { |
| CLOGE("[B%d P%d FD%d]Failed to free containerFd. ret %d", |
| bufIndex, planeIndex, m_buffer[bufIndex].containerFd[planeIndex], ret); |
| /* continue */ |
| } |
| } |
| |
| func_exit: |
| EXYNOS_CAMERA_BUFFER_OUT(); |
| |
| return ret; |
| } |
| |
| } // namespace android |