blob: 43575de614f5f28a3bc0a865dcaca79f6ee570af [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 "ExynosCameraMemoryAllocator"
#include "ExynosCameraMemory.h"
namespace android {
gralloc_module_t const *ExynosCameraGrallocAllocator::m_grallocHal;
gralloc_module_t const *ExynosCameraStreamAllocator::m_grallocHal;
ExynosCameraGraphicBufferAllocator::ExynosCameraGraphicBufferAllocator()
{
}
ExynosCameraGraphicBufferAllocator::~ExynosCameraGraphicBufferAllocator()
{
}
status_t ExynosCameraGraphicBufferAllocator::init(void)
{
m_width = 0;
m_height = 0;
m_stride = 0;
m_halPixelFormat = 0;
m_grallocUsage = GRALLOC_SET_USAGE_FOR_CAMERA;
for (int i = 0; i < VIDEO_MAX_FRAME; i++) {
m_flagGraphicBufferAlloc[i] = false;
m_privateHandle[i] = NULL;
}
return NO_ERROR;
}
status_t ExynosCameraGraphicBufferAllocator::setSize(int width, int height, int stride)
{
m_width = width;
m_height = height;
m_stride = stride;
return NO_ERROR;
}
status_t ExynosCameraGraphicBufferAllocator::getSize(int *width, int *height, int *stride)
{
*width = m_width;
*height = m_height;
*stride = m_stride;
return NO_ERROR;
}
status_t ExynosCameraGraphicBufferAllocator::setHalPixelFormat(int halPixelFormat)
{
m_halPixelFormat = halPixelFormat;
return NO_ERROR;
}
int ExynosCameraGraphicBufferAllocator::getHalPixelFormat(void)
{
return m_halPixelFormat;
}
status_t ExynosCameraGraphicBufferAllocator::setGrallocUsage(int grallocUsage)
{
m_grallocUsage = grallocUsage;
return NO_ERROR;
}
int ExynosCameraGraphicBufferAllocator::getGrallocUsage(void)
{
return m_grallocUsage;
}
sp<GraphicBuffer> ExynosCameraGraphicBufferAllocator::alloc(int index, int planeCount, int fdArr[], char *bufAddr[], unsigned int bufSize[])
{
if ((index < 0) || (index >= VIDEO_MAX_FRAME)) {
android_printAssert(NULL, LOG_TAG, "ASSERT(%s[%d]):Buffer index error (%d/%d), assert!!!!",
__FUNCTION__, __LINE__, index, VIDEO_MAX_FRAME);
}
sp<GraphicBuffer> graphicBuffer;
if (m_flagGraphicBufferAlloc[index] == false) {
graphicBuffer = m_alloc(index, planeCount, fdArr, bufAddr, bufSize, m_width, m_height, m_halPixelFormat, m_grallocUsage, m_stride);
if (graphicBuffer == 0) {
ALOGE("ERR(%s[%d]):m_alloc() fail", __FUNCTION__, __LINE__);
goto done;
}
} else {
graphicBuffer = m_graphicBuffer[index];
if (graphicBuffer == 0) {
ALOGE("ERR(%s[%d]):m_graphicBuffer[%d] == 0. so, fail", __FUNCTION__, __LINE__, index);
goto done;
}
}
done:
return graphicBuffer;
}
status_t ExynosCameraGraphicBufferAllocator::free(int index)
{
int ret = 0;
if (m_flagGraphicBufferAlloc[index] == false)
return NO_ERROR;
m_flagGraphicBufferAlloc[index] = false;
delete m_privateHandle[index];
m_privateHandle[index] = NULL;
m_graphicBuffer[index] = 0;
return NO_ERROR;
}
sp<GraphicBuffer> ExynosCameraGraphicBufferAllocator::m_alloc(int index,
int planeCount,
int fdArr[],
char *bufAddr[],
unsigned int bufSize[],
int width,
int height,
int halPixelFormat,
int grallocUsage,
int stride)
{
if (m_flagGraphicBufferAlloc[index] == true) {
ALOGE("ERR(%s[%d]):%d is already allocated. so, fail!!",
__FUNCTION__, __LINE__, index);
goto done;
}
if (planeCount <= 0) {
ALOGE("ERR(%s[%d]):invalid value : planeCount(%d). so, fail!!",
__FUNCTION__, __LINE__, planeCount);
goto done;
}
if (width == 0 || height == 0 || halPixelFormat == 0 || grallocUsage <= 0 || stride <= 0) {
ALOGE("ERR(%s[%d]):invalid value : width(%d), height(%d), halPixelFormat(%d), grallocUsage(%d), stride(%d). so, fail!!",
__FUNCTION__, __LINE__, width, height, halPixelFormat, grallocUsage, stride);
goto done;
}
if (planeCount == 1) {
m_privateHandle[index] = new private_handle_t(fdArr[0], -1, -1, bufSize[0], 0, 0, grallocUsage, width, height,
halPixelFormat, halPixelFormat, halPixelFormat, width, height, 0);
m_privateHandle[index]->base = (uint64_t)bufAddr[0];
m_privateHandle[index]->offset = 0;
} else {
android_printAssert(NULL, LOG_TAG, "ASSERT(%s[%d]):planeCount(%d) is not yet support, assert!!!!",
__FUNCTION__, __LINE__, planeCount);
}
ALOGV("DEBUG(%s[%d]):new GraphicBuffer(bufAddr(%p), width(%d), height(%d), halPixelFormat(%d), grallocUsage(%d), stride(%d), m_privateHandle[%d](%p), false)",
__FUNCTION__, __LINE__, bufAddr[0], width, height, halPixelFormat, grallocUsage, stride, index, m_privateHandle[index]);
m_graphicBuffer[index] = new GraphicBuffer((native_handle_t*)m_privateHandle[index], GraphicBuffer::WRAP_HANDLE,
width, height, (PixelFormat)halPixelFormat, 1, (uint64_t)grallocUsage, stride);
m_flagGraphicBufferAlloc[index] = true;
done:
return m_graphicBuffer[index];
}
ExynosCameraIonAllocator::ExynosCameraIonAllocator()
{
m_ionClient = 0;
m_ionAlign = 0;
m_ionHeapMask = 0;
m_ionFlags = 0;
}
ExynosCameraIonAllocator::~ExynosCameraIonAllocator()
{
ion_close(m_ionClient);
}
status_t ExynosCameraIonAllocator::init(bool isCached)
{
status_t ret = NO_ERROR;
if (m_ionClient == 0) {
m_ionClient = ion_open();
if (m_ionClient < 0) {
ALOGE("ERR(%s):ion_open failed", __FUNCTION__);
ret = BAD_VALUE;
goto func_exit;
}
}
m_ionAlign = 0;
m_ionHeapMask = ION_HEAP_SYSTEM_MASK;
m_ionFlags = (isCached == true ?
(ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC ) : 0);
func_exit:
return ret;
}
status_t ExynosCameraIonAllocator::alloc(
int size,
int *fd,
char **addr,
bool mapNeeded)
{
status_t ret = NO_ERROR;
int ionFd = 0;
char *ionAddr = NULL;
if (m_ionClient == 0) {
ALOGE("ERR(%s):allocator is not yet created", __FUNCTION__);
ret = INVALID_OPERATION;
goto func_exit;
}
if (size == 0) {
ALOGE("ERR(%s):size equals zero", __FUNCTION__);
ret = BAD_VALUE;
goto func_exit;
}
ret = ion_alloc_fd(m_ionClient, size, m_ionAlign, m_ionHeapMask, m_ionFlags, &ionFd);
if (ret < 0) {
ALOGE("ERR(%s):ion_alloc_fd(fd=%d) failed(%s)", __FUNCTION__, ionFd, strerror(errno));
ionFd = -1;
ret = INVALID_OPERATION;
goto func_exit;
}
if (mapNeeded == true) {
if (map(size, ionFd, &ionAddr) != NO_ERROR) {
ALOGE("ERR(%s):map failed", __FUNCTION__);
}
}
func_exit:
*fd = ionFd;
*addr = ionAddr;
return ret;
}
status_t ExynosCameraIonAllocator::alloc(
int size,
int *fd,
char **addr,
int mask,
int flags,
bool mapNeeded)
{
status_t ret = NO_ERROR;
int ionFd = 0;
char *ionAddr = NULL;
if (m_ionClient == 0) {
ALOGE("ERR(%s):allocator is not yet created", __FUNCTION__);
ret = INVALID_OPERATION;
goto func_exit;
}
if (size == 0) {
ALOGE("ERR(%s):size equals zero", __FUNCTION__);
ret = BAD_VALUE;
goto func_exit;
}
ret = ion_alloc_fd(m_ionClient, size, m_ionAlign, mask, flags, &ionFd);
if (ret < 0) {
ALOGE("ERR(%s):ion_alloc_fd(fd=%d) failed(%s)", __FUNCTION__, ionFd, strerror(errno));
ionFd = -1;
ret = INVALID_OPERATION;
goto func_exit;
}
if (mapNeeded == true) {
if (map(size, ionFd, &ionAddr) != NO_ERROR) {
ALOGE("ERR(%s):map failed", __FUNCTION__);
}
}
func_exit:
*fd = ionFd;
*addr = ionAddr;
return ret;
}
status_t ExynosCameraIonAllocator::free(
__unused int size,
int *fd,
char **addr,
bool mapNeeded)
{
status_t ret = NO_ERROR;
int ionFd = *fd;
char *ionAddr = *addr;
if (ionFd < 0) {
ALOGE("ERR(%s):ion_fd is lower than zero", __FUNCTION__);
ret = BAD_VALUE;
goto func_exit;
}
if (mapNeeded == true) {
if (ionAddr == NULL) {
ALOGE("ERR(%s):ion_addr equals NULL", __FUNCTION__);
ret = BAD_VALUE;
goto func_close_exit;
}
if (munmap(ionAddr, size) < 0) {
ALOGE("ERR(%s):munmap failed", __FUNCTION__);
ret = INVALID_OPERATION;
goto func_close_exit;
}
}
func_close_exit:
ion_close(ionFd);
ionFd = -1;
ionAddr = NULL;
func_exit:
*fd = ionFd;
*addr = ionAddr;
return ret;
}
status_t ExynosCameraIonAllocator::map(int size, int fd, char **addr)
{
status_t ret = NO_ERROR;
char *ionAddr = NULL;
if (size == 0) {
ALOGE("ERR(%s):size equals zero", __FUNCTION__);
ret = BAD_VALUE;
goto func_exit;
}
if (fd <= 0) {
ALOGE("ERR(%s):fd=%d failed", __FUNCTION__, fd);
ret = BAD_VALUE;
goto func_exit;
}
ionAddr = (char *)mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (ionAddr == (char *)MAP_FAILED || ionAddr == NULL) {
ALOGE("ERR(%s):ion_map(size=%d) failed, (fd=%d), (%s)", __FUNCTION__, size, fd, strerror(errno));
close(fd);
ionAddr = NULL;
ret = INVALID_OPERATION;
goto func_exit;
}
func_exit:
*addr = ionAddr;
return ret;
}
void ExynosCameraIonAllocator::setIonHeapMask(int mask)
{
m_ionHeapMask |= mask;
}
void ExynosCameraIonAllocator::setIonFlags(int flags)
{
m_ionFlags |= flags;
}
ExynosCameraMHBAllocator::ExynosCameraMHBAllocator()
{
m_allocator = NULL;
}
ExynosCameraMHBAllocator::~ExynosCameraMHBAllocator()
{
}
status_t ExynosCameraMHBAllocator::init(camera_request_memory allocator)
{
m_allocator = allocator;
return NO_ERROR;
}
status_t ExynosCameraMHBAllocator::alloc(
int size,
int *fd,
char **addr,
int numBufs,
camera_memory_t **heap)
{
status_t ret = NO_ERROR;
camera_memory_t *heap_ptr = NULL;
int heapFd = 0;
char *heapAddr = NULL;
if (m_allocator == NULL) {
ALOGE("ERR(%s):m_allocator equals NULL", __FUNCTION__);
ret = INVALID_OPERATION;
goto func_exit;
}
heap_ptr = m_allocator(-1, size, numBufs, &heapFd);
if (heap_ptr == NULL || heapFd < 0) {
ALOGE("ERR(%s):heap_alloc(size=%d) failed", __FUNCTION__, size);
heap_ptr = NULL;
heapFd = -1;
ret = BAD_VALUE;
goto func_exit;
}
heapAddr = (char *)heap_ptr->data;
func_exit:
*fd = heapFd;
*addr = heapAddr;
*heap = heap_ptr;
#ifdef EXYNOS_CAMERA_MEMORY_TRACE
ALOGI("INFO(%s[%d]):[heap.fd=%d] .addr=%p .heap=%p]",
__FUNCTION__, __LINE__, heapFd, heapAddr, heap_ptr);
#endif
return ret;
}
status_t ExynosCameraMHBAllocator::free(
__unused int size,
int *fd,
char **addr,
camera_memory_t **heap)
{
status_t ret = NO_ERROR;
camera_memory_t *heap_ptr = *heap;
int heapFd = *fd;
char *heapAddr = *addr;
if (heap_ptr == NULL) {
ALOGE("ERR(%s):heap_ptr equals NULL", __FUNCTION__);
ret = INVALID_OPERATION;
goto func_exit;
}
heap_ptr->release(heap_ptr);
heapAddr = NULL;
heapFd = -1;
heap_ptr = 0;
func_exit:
*fd = heapFd;
*addr = heapAddr;
*heap = heap_ptr;
return ret;
}
ExynosCameraGrallocAllocator::ExynosCameraGrallocAllocator()
{
m_allocator = NULL;
m_minUndequeueBufferMargin = 0;
if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **)&m_grallocHal))
ALOGE("ERR(%s):Loading gralloc HAL failed", __FUNCTION__);
m_grallocUsage = GRALLOC_SET_USAGE_FOR_CAMERA;
}
ExynosCameraGrallocAllocator::~ExynosCameraGrallocAllocator()
{
m_minUndequeueBufferMargin = 0;
}
status_t ExynosCameraGrallocAllocator::init(
preview_stream_ops *allocator,
int bufCount,
int minUndequeueBufferCount)
{
status_t ret = NO_ERROR;
ret = init(allocator, bufCount, minUndequeueBufferCount, GRALLOC_SET_USAGE_FOR_CAMERA);
return ret;
}
status_t ExynosCameraGrallocAllocator::init(
preview_stream_ops *allocator,
int bufCount,
int minUndequeueBufferCount,
int grallocUsage)
{
status_t ret = NO_ERROR;
m_allocator = allocator;
if( minUndequeueBufferCount < 0 ) {
m_minUndequeueBufferMargin = 0;
} else {
m_minUndequeueBufferMargin = minUndequeueBufferCount;
}
if (setBufferCount(bufCount) != 0) {
ALOGE("ERR(%s):setBufferCount failed", __FUNCTION__);
ret = INVALID_OPERATION;
goto func_exit;
}
if (m_allocator == NULL) {
ALOGE("ERR(%s):m_allocator equals NULL", __FUNCTION__);
ret = INVALID_OPERATION;
goto func_exit;
}
if (m_allocator->set_usage(m_allocator, grallocUsage) != 0) {
ALOGE("ERR(%s):set_usage failed", __FUNCTION__);
ret = INVALID_OPERATION;
goto func_exit;
}
m_grallocUsage = grallocUsage;
m_halPixelFormat = 0;
if (m_grallocHal == NULL) {
if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **)&m_grallocHal))
ALOGE("ERR(%s):Loading gralloc HAL failed", __FUNCTION__);
}
func_exit:
return ret;
}
status_t ExynosCameraGrallocAllocator::alloc(
buffer_handle_t **bufHandle,
int fd[],
char *addr[],
int *bufStride,
bool *isLocked)
{
status_t ret = NO_ERROR;
int width = 0;
int height = 0;
void *grallocAddr[3] = {NULL};
int grallocFd[3] = {0};
android_ycbcr ycbcr;
const private_handle_t *priv_handle = NULL;
int retryCount = 5;
ExynosCameraDurationTimer dequeuebufferTimer;
ExynosCameraDurationTimer lockbufferTimer;
for (int retryCount = 5; retryCount > 0; retryCount--) {
#ifdef EXYNOS_CAMERA_MEMORY_TRACE
ALOGI("INFO(%s[%d]):dequeue_buffer retryCount=%d",
__FUNCTION__, __LINE__, retryCount);
#endif
if (m_allocator == NULL) {
ALOGE("ERR(%s):m_allocator equals NULL", __FUNCTION__);
ret = INVALID_OPERATION;
goto func_exit;
}
dequeuebufferTimer.start();
ret = m_allocator->dequeue_buffer(m_allocator, bufHandle, bufStride);
dequeuebufferTimer.stop();
#if defined (EXYNOS_CAMERA_MEMORY_TRACE_GRALLOC_PERFORMANCE)
ALOGD("DEBUG(%s[%d]):Check dequeue buffer performance, duration(%lld usec)",
__FUNCTION__, __LINE__, dequeuebufferTimer.durationUsecs());
#else
if (dequeuebufferTimer.durationMsecs() > GRALLOC_WARNING_DURATION_MSEC)
ALOGW("WRN(%s[%d]):dequeue_buffer() duration(%lld msec)",
__FUNCTION__, __LINE__, dequeuebufferTimer.durationMsecs());
#endif
if (ret == NO_INIT) {
ALOGW("WARN(%s):BufferQueue is abandoned", __FUNCTION__);
return ret;
} else if (ret != 0) {
ALOGE("ERR(%s):dequeue_buffer failed", __FUNCTION__);
continue;
}
if (bufHandle == NULL) {
ALOGE("ERR(%s):bufHandle == NULL failed, retry(%d)", __FUNCTION__, retryCount);
continue;
}
lockbufferTimer.start();
ret = m_allocator->lock_buffer(m_allocator, *bufHandle);
lockbufferTimer.stop();
if (ret != 0)
ALOGE("ERR(%s):lock_buffer failed, but go on to the next step ...", __FUNCTION__);
#if defined (EXYNOS_CAMERA_MEMORY_TRACE_GRALLOC_PERFORMANCE)
ALOGD("DEBUG(%s[%d]):Check lock buffer performance, duration(%lld usec)",
__FUNCTION__, __LINE__, lockbufferTimer.durationUsecs());
#else
if (lockbufferTimer.durationMsecs() > GRALLOC_WARNING_DURATION_MSEC)
ALOGW("WRN(%s[%d]):lock_buffer() duration(%lld msec)",
__FUNCTION__, __LINE__, lockbufferTimer.durationMsecs());
#endif
if (*isLocked == false) {
lockbufferTimer.start();
ret = m_grallocHal->lock_ycbcr(m_grallocHal, **bufHandle, GRALLOC_LOCK_FOR_CAMERA,
0, 0,/* left, top */ width, height, &ycbcr);
lockbufferTimer.stop();
#if defined (EXYNOS_CAMERA_MEMORY_TRACE_GRALLOC_PERFORMANCE)
ALOGD("DEBUG(%s[%d]):Check grallocHAL lock performance, duration(%lld usec)",
__FUNCTION__, __LINE__, lockbufferTimer.durationUsecs());
#else
if (lockbufferTimer.durationMsecs() > GRALLOC_WARNING_DURATION_MSEC)
ALOGW("WRN(%s[%d]):grallocHAL->lock_ycbcr() duration(%lld msec)",
__FUNCTION__, __LINE__, lockbufferTimer.durationMsecs());
#endif
if (ret != 0) {
ALOGE("ERR(%s):grallocHal->lock_ycbcr failed.. retry", __FUNCTION__);
if (m_allocator->cancel_buffer(m_allocator, *bufHandle) != 0)
ALOGE("ERR(%s):cancel_buffer failed", __FUNCTION__);
ret = INVALID_OPERATION;
goto func_exit;
}
break;
}
}
if (bufHandle == NULL) {
ALOGE("ERR(%s):bufHandle == NULL failed", __FUNCTION__);
ret = INVALID_OPERATION;
goto func_exit;
}
if (*bufHandle == NULL) {
ALOGE("@@@@ERR(%s):*bufHandle == NULL failed", __FUNCTION__);
ret = INVALID_OPERATION;
goto func_exit;
}
priv_handle = private_handle_t::dynamicCast(**bufHandle);
grallocFd[0] = priv_handle->fd;
grallocFd[1] = priv_handle->fd1;
grallocFd[2] = priv_handle->fd2;
*isLocked = true;
func_exit:
switch (m_halPixelFormat) {
/* three plane */
case HAL_PIXEL_FORMAT_EXYNOS_YV12_M:
fd[2] = grallocFd[2];
addr[2] = (char *)ycbcr.cr;
/* two plane */
case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M:
case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL:
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M:
fd[1] = grallocFd[1];
if (m_halPixelFormat == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M) {
addr[1] = (char *)ycbcr.cb;
} else if (m_halPixelFormat == HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M ||
m_halPixelFormat == HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL) {
addr[1] = (char *)ycbcr.cr;
}
/* one plane */
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
case HAL_PIXEL_FORMAT_YV12:
fd[0] = grallocFd[0];
addr[0] = (char *)ycbcr.y;
break;
default:
android_printAssert(NULL, LOG_TAG, "invalid halPixelFormat(%x)", m_halPixelFormat);
break;
}
return ret;
}
status_t ExynosCameraGrallocAllocator::free(buffer_handle_t *bufHandle, bool isLocked)
{
status_t ret = NO_ERROR;
if (bufHandle == NULL) {
ALOGE("ERR(%s):bufHandle equals NULL", __FUNCTION__);
ret = INVALID_OPERATION;
goto func_exit;
}
if (isLocked == true) {
if (m_grallocHal->unlock(m_grallocHal, *bufHandle) != 0) {
ALOGE("ERR(%s):grallocHal->unlock failed", __FUNCTION__);
ret = INVALID_OPERATION;
goto func_exit;
}
}
if (m_allocator == NULL) {
ALOGE("ERR(%s):m_allocator equals NULL", __FUNCTION__);
ret = INVALID_OPERATION;
goto func_exit;
}
if (m_allocator->cancel_buffer(m_allocator, bufHandle) != 0) {
ALOGE("ERR(%s):cancel_buffer failed", __FUNCTION__);
ret = INVALID_OPERATION;
goto func_exit;
}
func_exit:
return ret;
}
status_t ExynosCameraGrallocAllocator::setBufferCount(int bufCount)
{
status_t ret = NO_ERROR;
if (m_allocator == NULL) {
ALOGE("ERR(%s):m_allocator equals NULL", __FUNCTION__);
ret = INVALID_OPERATION;
return ret;
}
if (m_allocator->set_buffer_count(m_allocator, bufCount) != 0) {
ALOGE("ERR(%s):set_buffer_count failed [bufCount=%d]", __FUNCTION__, bufCount);
ret = INVALID_OPERATION;
}
return ret;
}
status_t ExynosCameraGrallocAllocator::setBuffersGeometry(
int width,
int height,
int halPixelFormat)
{
status_t ret = NO_ERROR;
if (m_allocator == NULL) {
ALOGE("ERR(%s):m_allocator equals NULL", __FUNCTION__);
ret = INVALID_OPERATION;
return ret;
}
if (m_allocator->set_buffers_geometry(
m_allocator,
width, height,
halPixelFormat) != 0) {
ALOGE("ERR(%s):set_buffers_geometry failed", __FUNCTION__);
ret = INVALID_OPERATION;
}
m_halPixelFormat = halPixelFormat;
return ret;
}
int ExynosCameraGrallocAllocator::getGrallocUsage(void)
{
return m_grallocUsage;
}
status_t ExynosCameraGrallocAllocator::getAllocator(preview_stream_ops **allocator)
{
*allocator = m_allocator;
return NO_ERROR;
}
int ExynosCameraGrallocAllocator::getMinUndequeueBuffer()
{
int minUndeqBufCount = 0;
if (m_allocator == NULL) {
ALOGE("ERR(%s):m_allocator equals NULL", __FUNCTION__);
return INVALID_OPERATION;
}
if (m_allocator->get_min_undequeued_buffer_count(m_allocator, &minUndeqBufCount) != 0) {
ALOGE("ERR(%s):enqueue_buffer failed", __FUNCTION__);
return INVALID_OPERATION;
}
return minUndeqBufCount < 2 ? (minUndeqBufCount + m_minUndequeueBufferMargin) : minUndeqBufCount;
}
status_t ExynosCameraGrallocAllocator::dequeueBuffer(
buffer_handle_t **bufHandle,
int fd[],
char *addr[],
bool *isLocked, Mutex *lock)
{
int bufStride = 0;
status_t ret = NO_ERROR;
lock->unlock();
ret = alloc(bufHandle, fd, addr, &bufStride, isLocked);
lock->lock();
if (ret == NO_INIT) {
ALOGW("WARN(%s):BufferQueue is abandoned", __FUNCTION__);
return ret;
} else if (ret != NO_ERROR) {
ALOGE("ERR(%s):alloc failed", __FUNCTION__);
return INVALID_OPERATION;
}
return NO_ERROR;
}
status_t ExynosCameraGrallocAllocator::enqueueBuffer(buffer_handle_t *handle, Mutex *lock)
{
status_t ret = NO_ERROR;
ExynosCameraDurationTimer enqueuebufferTimer;
if (m_allocator == NULL) {
ALOGE("ERR(%s):m_allocator equals NULL", __FUNCTION__);
return INVALID_OPERATION;
}
enqueuebufferTimer.start();
lock->unlock();
ret = m_allocator->enqueue_buffer(m_allocator, handle);
lock->lock();
enqueuebufferTimer.stop();
#if defined (EXYNOS_CAMERA_MEMORY_TRACE_GRALLOC_PERFORMANCE)
ALOGD("DEBUG(%s[%d]):Check enqueue buffer performance, duration(%lld usec)",
__FUNCTION__, __LINE__, enqueuebufferTimer.durationUsecs());
#else
if (enqueuebufferTimer.durationMsecs() > GRALLOC_WARNING_DURATION_MSEC)
ALOGW("WRN(%s[%d]):enqueue_buffer() duration(%lld msec)",
__FUNCTION__, __LINE__, enqueuebufferTimer.durationMsecs());
#endif
if (ret != 0) {
ALOGE("ERR(%s):enqueue_buffer failed", __FUNCTION__);
return INVALID_OPERATION;
}
return NO_ERROR;
}
status_t ExynosCameraGrallocAllocator::cancelBuffer(buffer_handle_t *handle, Mutex *lock)
{
status_t ret = NO_ERROR;
ExynosCameraDurationTimer cancelbufferTimer;
if (m_allocator == NULL) {
ALOGE("ERR(%s):m_allocator equals NULL", __FUNCTION__);
return INVALID_OPERATION;
}
if (m_grallocHal->unlock(m_grallocHal, *handle) != 0) {
ALOGE("ERR(%s):grallocHal->unlock failed", __FUNCTION__);
return INVALID_OPERATION;
}
cancelbufferTimer.start();
lock->unlock();
ret = m_allocator->cancel_buffer(m_allocator, handle);
lock->lock();
cancelbufferTimer.stop();
#if defined (EXYNOS_CAMERA_MEMORY_TRACE_GRALLOC_PERFORMANCE)
ALOGD("DEBUG(%s[%d]):Check cancel buffer performance, duration(%lld usec)",
__FUNCTION__, __LINE__, cancelbufferTimer.durationUsecs());
#else
if (cancelbufferTimer.durationMsecs() > GRALLOC_WARNING_DURATION_MSEC)
ALOGW("WRN(%s[%d]):cancel_buffer() duration(%lld msec)",
__FUNCTION__, __LINE__, cancelbufferTimer.durationMsecs());
#endif
if (ret != 0) {
ALOGE("ERR(%s):cancel_buffer failed", __FUNCTION__);
return INVALID_OPERATION;
}
return NO_ERROR;
}
ExynosCameraStreamAllocator::ExynosCameraStreamAllocator()
{
m_allocator = NULL;
if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **)&m_grallocHal))
ALOGE("ERR(%s):Loading gralloc HAL failed", __FUNCTION__);
}
ExynosCameraStreamAllocator::~ExynosCameraStreamAllocator()
{
}
status_t ExynosCameraStreamAllocator::init(camera3_stream_t *allocator)
{
status_t ret = NO_ERROR;
m_allocator = allocator;
return ret;
}
int ExynosCameraStreamAllocator::lock(
buffer_handle_t **bufHandle,
int fd[],
char *addr[],
bool *isLocked,
int planeCount)
{
int ret = 0;
uint32_t width = 0;
uint32_t height = 0;
uint32_t usage = 0;
uint32_t format = 0;
void *grallocAddr[3] = {NULL};
const private_handle_t *priv_handle = NULL;
int grallocFd[3] = {0};
android_ycbcr ycbcr;
ExynosCameraDurationTimer lockbufferTimer;
if (bufHandle == NULL) {
ALOGE("ERR(%s):bufHandle equals NULL, failed", __FUNCTION__);
ret = INVALID_OPERATION;
goto func_exit;
}
if (*bufHandle == NULL) {
ALOGE("ERR(%s):*bufHandle == NULL, failed", __FUNCTION__);
ret = INVALID_OPERATION;
goto func_exit;
}
width = m_allocator->width;
height = m_allocator->height;
usage = m_allocator->usage;
format = m_allocator->format;
switch (format) {
case HAL_PIXEL_FORMAT_EXYNOS_ARGB_8888:
case HAL_PIXEL_FORMAT_RGBA_8888:
case HAL_PIXEL_FORMAT_RGBX_8888:
case HAL_PIXEL_FORMAT_BGRA_8888:
case HAL_PIXEL_FORMAT_RGB_888:
case HAL_PIXEL_FORMAT_RGB_565:
case HAL_PIXEL_FORMAT_RAW16:
case HAL_PIXEL_FORMAT_RAW_OPAQUE:
case HAL_PIXEL_FORMAT_BLOB:
case HAL_PIXEL_FORMAT_YCbCr_422_I:
if (planeCount == 1) {
lockbufferTimer.start();
ret = m_grallocHal->lock(
m_grallocHal,
**bufHandle,
usage,
0, 0, /* left, top */
width, height,
grallocAddr);
lockbufferTimer.stop();
break;
}
default:
android_ycbcr ycbcr;
lockbufferTimer.start();
ret = m_grallocHal->lock_ycbcr(
m_grallocHal,
**bufHandle,
usage,
0, 0, /* left, top */
width, height,
&ycbcr);
lockbufferTimer.stop();
break;
}
#if defined (EXYNOS_CAMERA_MEMORY_TRACE_GRALLOC_PERFORMANCE)
ALOGD("DEBUG(%s[%d]):Check grallocHAL lock performance, duration(%lld usec)",
__FUNCTION__, __LINE__, lockbufferTimer.durationUsecs());
#else
if (lockbufferTimer.durationMsecs() > GRALLOC_WARNING_DURATION_MSEC)
ALOGW("WRN(%s[%d]):grallocHAL->lock() duration(%lld msec)",
__FUNCTION__, __LINE__, lockbufferTimer.durationMsecs());
#endif
if (ret != 0) {
ALOGE("ERR(%s):grallocHal->lock failed.. ", __FUNCTION__);
goto func_exit;
}
priv_handle = private_handle_t::dynamicCast(**bufHandle);
switch (planeCount) {
case 3:
grallocFd[2] = priv_handle->fd2;
grallocAddr[2] = ycbcr.cr;
case 2:
grallocFd[1] = priv_handle->fd1;
grallocAddr[1] = ycbcr.cb;
case 1:
grallocFd[0] = priv_handle->fd;
if (grallocAddr[0] == NULL) {
grallocAddr[0] = ycbcr.y;
}
break;
default:
break;
}
*isLocked = true;
func_exit:
switch (planeCount) {
case 3:
fd[2] = grallocFd[2];
addr[2] = (char *)grallocAddr[2];
case 2:
fd[1] = grallocFd[1];
addr[1] = (char *)grallocAddr[1];
case 1:
fd[0] = grallocFd[0];
addr[0] = (char *)grallocAddr[0];
break;
default:
break;
}
return ret;
}
int ExynosCameraStreamAllocator::unlock(buffer_handle_t *bufHandle)
{
int ret = 0;
if (bufHandle == NULL) {
ALOGE("ERR(%s):bufHandle equals NULL", __FUNCTION__);
ret = INVALID_OPERATION;
goto func_exit;
}
ret = m_grallocHal->unlock(m_grallocHal, *bufHandle);
if (ret != 0)
ALOGE("ERR(%s):grallocHal->unlock failed", __FUNCTION__);
func_exit:
return ret;
}
}