android13/hardware/rockchip/camera/psl/CameraBuffer.cpp

872 lines
28 KiB
C++

/*
* Copyright (C) 2013-2017 Intel Corporation
* Copyright (c) 2017, Fuzhou Rockchip 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 on 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 "CameraBuffer"
#include "LogHelper.h"
#include <sys/mman.h>
#include "PlatformData.h"
#include "CameraBuffer.h"
#include "CameraStream.h"
#include "Camera3GFXFormat.h"
#include "CameraMetadataHelper.h"
#include <unistd.h>
#include <sync/sync.h>
#include <sys/types.h>
#include <dirent.h>
#include <algorithm>
namespace android {
namespace camera2 {
extern int32_t gDumpInterval;
extern int32_t gDumpCount;
////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
////////////////////////////////////////////////////////////////////
/**
* CameraBuffer
*
* Default constructor
* This constructor is used when we pre-allocate the CameraBuffer object
* The initialization will be done as a second stage wit the method
* init(), where we initialize the wrapper with the gralloc buffer provided by
* the framework
*/
CameraBuffer::CameraBuffer() : mWidth(0),
mHeight(0),
mSize(0),
mFormat(0),
mV4L2Fmt(0),
mStride(0),
mUsage(0),
mInit(false),
mLocked(false),
mRegistered(false),
mType(BUF_TYPE_HANDLE),
mGbmBufferManager(nullptr),
mHandle(nullptr),
mHandlePtr(nullptr),
mOwner(nullptr),
mDataPtr(nullptr),
mRequestID(0),
mpSyncFence(nullptr),
captureDoned(false),
mCameraId(0),
mDmaBufFd(-1)
{
LOGI("%s default constructor for buf %p", __FUNCTION__, this);
CLEAR(mUserBuffer);
CLEAR(mTimestamp);
mUserBuffer.release_fence = -1;
mUserBuffer.acquire_fence = -1;
}
/**
* CameraBuffer
*
* Constructor for buffers allocated using MemoryUtils::allocateHeapBuffer
*
* \param w [IN] width
* \param h [IN] height
* \param s [IN] stride
* \param v4l2fmt [IN] V4l2 format
* \param usrPtr [IN] Data pointer
* \param cameraId [IN] id of camera being used
* \param dataSizeOverride [IN] buffer size input. Default is 0 and frameSize()
is used in that case.
*/
CameraBuffer::CameraBuffer(int w,
int h,
int s,
int v4l2fmt,
void* usrPtr,
int cameraId,
int dataSizeOverride):
mWidth(w),
mHeight(h),
mSize(0),
mFormat(0),
mV4L2Fmt(v4l2fmt),
mStride(s),
mUsage(0),
mInit(false),
mLocked(true),
mRegistered(false),
mType(BUF_TYPE_MALLOC),
mGbmBufferManager(nullptr),
mHandle(nullptr),
mHandlePtr(nullptr),
mOwner(nullptr),
mDataPtr(nullptr),
mRequestID(0),
mpSyncFence(nullptr),
captureDoned(false),
mCameraId(cameraId),
mDmaBufFd(-1)
{
LOGI("%s create malloc camera buffer %p", __FUNCTION__, this);
if (usrPtr != nullptr) {
mDataPtr = usrPtr;
mInit = true;
mSize = dataSizeOverride ? dataSizeOverride : frameSize(mV4L2Fmt, mStride, mHeight);
mFormat = v4L2Fmt2GFXFmt(v4l2fmt);
} else {
LOGE("Tried to initialize a buffer with nullptr ptr!!");
}
CLEAR(mUserBuffer);
CLEAR(mTimestamp);
mUserBuffer.release_fence = -1;
mUserBuffer.acquire_fence = -1;
}
/**
* CameraBuffer
*
* Constructor for buffers allocated using mmap
*
* \param w [IN] width
* \param h [IN] height
* \param s [IN] stride
* \param fd [IN] File descriptor to map
* \param dmaBufFd [IN] File descriptor for dmabuf
* \param length [IN] amount of data to map
* \param v4l2fmt [IN] Pixel format in V4L2 enum
* \param offset [IN] offset from the begining of the file (mmap param)
* \param prot [IN] memory protection (mmap param)
* \param flags [IN] flags (mmap param)
*
* Success of the mmap can be queried by checking the size of the resulting
* buffer
*/
CameraBuffer::CameraBuffer(int w, int h, int s, int fd, int dmaBufFd, int length,
int v4l2fmt, int offset, int prot, int flags):
mWidth(w),
mHeight(h),
mSize(length),
mFormat(0),
mV4L2Fmt(v4l2fmt),
mStride(s),
mUsage(0),
mInit(false),
mLocked(false),
mRegistered(false),
mType(BUF_TYPE_MMAP),
mGbmBufferManager(nullptr),
mHandle(nullptr),
mHandlePtr(nullptr),
mOwner(nullptr),
mDataPtr(nullptr),
mRequestID(0),
mpSyncFence(nullptr),
captureDoned(false),
mCameraId(-1),
mDmaBufFd(dmaBufFd)
{
LOGI("%s create mmap camera buffer %p", __FUNCTION__, this);
mLocked = true;
mInit = true;
CLEAR(mUserBuffer);
CLEAR(mTimestamp);
CLEAR(mHandle);
mUserBuffer.release_fence = -1;
mUserBuffer.acquire_fence = -1;
mDataPtr = mmap(nullptr, length, prot, flags, fd, offset);
if (CC_UNLIKELY(mDataPtr == MAP_FAILED)) {
LOGE("Failed to MMAP the buffer %s", strerror(errno));
mDataPtr = nullptr;
return;
}
LOGI("mmaped address for %p length %d", mDataPtr, mSize);
}
/**
* init
*
* Constructor to wrap a camera3_stream_buffer
*
* \param aBuffer [IN] camera3_stream_buffer buffer
*/
status_t CameraBuffer::init(const camera3_stream_buffer *aBuffer, int cameraId)
{
mType = BUF_TYPE_HANDLE;
mGbmBufferManager = arc::CameraBufferManager::GetInstance();
mHandle = *aBuffer->buffer;
mHandlePtr = aBuffer->buffer;
mWidth = aBuffer->stream->width;
mHeight = aBuffer->stream->height;
mFormat = aBuffer->stream->format;
mV4L2Fmt = mGbmBufferManager->GetV4L2PixelFormat(mHandle);
// Use actual width from platform native handle for stride
mStride = mGbmBufferManager->GetPlaneStride(*aBuffer->buffer, 0);
mSize = 0;
mLocked = false;
mOwner = static_cast<CameraStream*>(aBuffer->stream->priv);
mUsage = mOwner->usage()|RK_GRALLOC_USAGE_SPECIFY_STRIDE;
#ifdef GRALLOC_USAGE_RGA_ACCESS
mUsage = mUsage|RK_GRALLOC_USAGE_RGA_ACCESS;
#endif
mInit = true;
mDataPtr = nullptr;
mUserBuffer = *aBuffer;
captureDoned = false;
char fenceName[32] = {};
snprintf(fenceName, sizeof(fenceName),
"%dx%d_%s_%d", mWidth, mHeight, v4l2Fmt2Str(mV4L2Fmt), cameraId);
mpSyncFence = std::make_shared<SyncFence>(1, fenceName);
CheckError(!mpSyncFence.get(), UNKNOWN_ERROR, "@%s, No memory for new SyncFence",
__FUNCTION__);
// the fence fd passing to framework must make a dup because framework
// will make a dup to this fd and close this fd as soon, we still need to
// access the fd to signal the fence in this case. so must do a dup.
mUserBuffer.release_fence = mpSyncFence->dup();
/* mUserBuffer.release_fence = -1; */
mCameraId = cameraId;
LOGI("@%s, mHandle:%p, mHandlePtr:%p, mFormat:%d, mWidth:%d, mHeight:%d, mStride:%d, mSize:%d, V4l2Fmt:%s, reqId:%d",
__FUNCTION__, mHandle, mHandlePtr, mFormat, mWidth, mHeight, mStride, mSize, v4l2Fmt2Str(mV4L2Fmt), mRequestID);
if (mHandle == nullptr) {
LOGE("@%s: invalid buffer handle", __FUNCTION__);
mUserBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
return BAD_VALUE;
}
int ret = registerBuffer();
LOGI("@%s,after register mHandle:%p, mHandlePtr:%p",__FUNCTION__, mHandle, mHandlePtr);
if (ret) {
mUserBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
return UNKNOWN_ERROR;
}
/* TODO: add some consistency checks here and return an error */
return NO_ERROR;
}
void CameraBuffer::reConfig(int w, int h){
LOGD("@%s, enter: wxh(%dx%d)", __FUNCTION__, w, h);
mWidth = w;
mHeight =h;
mStride = w;
}
status_t CameraBuffer::init(const camera3_stream_t* stream,
buffer_handle_t handle)
{
mType = BUF_TYPE_HANDLE;
mGbmBufferManager = arc::CameraBufferManager::GetInstance();
mHandle = handle;
mWidth = stream->width;
mHeight = stream->height;
mFormat = stream->format;
mV4L2Fmt = mGbmBufferManager->GetV4L2PixelFormat(mHandle);
// Use actual width from platform native handle for stride
mStride = mGbmBufferManager->GetPlaneStride(handle, 0);
mSize = 0;
mLocked = false;
mOwner = nullptr;
mUsage = stream->usage|RK_GRALLOC_USAGE_SPECIFY_STRIDE;
mInit = true;
mDataPtr = nullptr;
CLEAR(mUserBuffer);
mUserBuffer.acquire_fence = -1;
mUserBuffer.release_fence = -1;
// hal internal buffer, just lock it and unlock in destruct function
// mSize filled here
lock();
LOGI("@%s, mHandle:%p, mFormat:%d, mWidth:%d, mHeight:%d, mStride:%d, mSize:%d, V4l2Fmt:%s",
__FUNCTION__, mHandle, mFormat, mWidth, mHeight, mStride, mSize, v4l2Fmt2Str(mV4L2Fmt));
return NO_ERROR;
}
status_t CameraBuffer::deinit()
{
return deregisterBuffer();
}
CameraBuffer::~CameraBuffer()
{
HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH);
if (mInit) {
switch(mType) {
case BUF_TYPE_MALLOC:
free(mDataPtr);
mDataPtr = nullptr;
break;
case BUF_TYPE_MMAP:
if (mDataPtr != nullptr)
munmap(mDataPtr, mSize);
mDataPtr = nullptr;
mSize = 0;
close(mDmaBufFd);
break;
case BUF_TYPE_HANDLE:
// Allocated by the HAL
if (!(mUserBuffer.stream)) {
LOGI("release internal buffer");
if(isLocked())
unlock();
mGbmBufferManager->Free(mHandle);
}
break;
default:
break;
}
}
LOGI("%s destroying buf %p", __FUNCTION__, this);
}
status_t CameraBuffer::waitOnAcquireFence()
{
const int WAIT_TIME_OUT_MS = 300;
const int BUFFER_READY = -1;
if (mUserBuffer.acquire_fence != BUFFER_READY) {
PERFORMANCE_ATRACE_NAME("waitOnAcquireFence");
LOGI("%s: Fence in HAL is %d", __FUNCTION__, mUserBuffer.acquire_fence);
int ret = sync_wait(mUserBuffer.acquire_fence, WAIT_TIME_OUT_MS);
if (ret) {
mUserBuffer.release_fence = mUserBuffer.acquire_fence;
mUserBuffer.acquire_fence = -1;
mUserBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
LOGE("Buffer sync_wait %d fail!", mUserBuffer.release_fence);
return TIMED_OUT;
} else {
close(mUserBuffer.acquire_fence);
}
mUserBuffer.acquire_fence = BUFFER_READY;
}
return NO_ERROR;
}
/**
* getFence
*
* return the fecne to request result
*/
status_t CameraBuffer::getFence(camera3_stream_buffer* buf)
{
if (!buf)
return BAD_VALUE;
buf->acquire_fence = mUserBuffer.acquire_fence;
buf->release_fence = mUserBuffer.release_fence;
return NO_ERROR;
}
status_t CameraBuffer::registerBuffer()
{
#ifdef RK_GRALLOC_4
buffer_handle_t outbuffer;
int ret = mGbmBufferManager->Register(mHandle, &outbuffer);
if (ret == 0) {
mHandle = outbuffer;
mHandlePtr = &outbuffer;
}
#else
int ret = mGbmBufferManager->Register(mHandle);
#endif
if (ret < 0) {
LOGE("@%s: call Register fail, mHandle:%p, ret:%d", __FUNCTION__, mHandle, ret);
return UNKNOWN_ERROR;
}
mRegistered = true;
return NO_ERROR;
}
status_t CameraBuffer::deregisterBuffer()
{
if (mRegistered) {
int ret = mGbmBufferManager->Deregister(mHandle);
if (ret) {
LOGE("@%s: call Deregister fail, mHandle:%p, ret:%d", __FUNCTION__, mHandle, ret);
return UNKNOWN_ERROR;
}
mRegistered = false;
}
return NO_ERROR;
}
/**
* lock
*
* lock the gralloc buffer with specified flags
*
* \param aBuffer [IN] int flags
*/
status_t CameraBuffer::lock(int flags)
{
HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH);
mDataPtr = nullptr;
mSize = 0;
int ret = 0;
uint32_t planeNum = mGbmBufferManager->GetNumPlanes(mHandle);
LOGI("@%s, planeNum:%d, mHandle:%p, mFormat:%d", __FUNCTION__, planeNum, mHandle, mFormat);
if (planeNum == 1) {
void* data = nullptr;
ret = (mFormat == HAL_PIXEL_FORMAT_BLOB)
? mGbmBufferManager->Lock(mHandle, flags, 0, 0, mStride > mWidth ? mWidth : mStride, 1, &data)
: mGbmBufferManager->Lock(mHandle, flags, 0, 0, mWidth, mHeight, &data);
if (ret) {
LOGE("@%s: call Lock fail, mHandle:%p", __FUNCTION__, mHandle);
return UNKNOWN_ERROR;
}
mDataPtr = data;
} else if (planeNum > 1) {
struct android_ycbcr ycbrData;
ret = mGbmBufferManager->LockYCbCr(mHandle, flags, 0, 0, mWidth, mHeight, &ycbrData);
if (ret) {
LOGE("@%s: call LockYCbCr fail, mHandle:%p", __FUNCTION__, mHandle);
return UNKNOWN_ERROR;
}
mDataPtr = ycbrData.y;
} else {
LOGE("ERROR @%s: planeNum is 0", __FUNCTION__);
return UNKNOWN_ERROR;
}
if (ret) {
LOGE("ERROR @%s: Failed to lock buffer! %d", __FUNCTION__, ret);
return UNKNOWN_ERROR;
}
for (int i = 0; i < planeNum; i++) {
mSize += mGbmBufferManager->GetPlaneSize(mHandle, i);
LOGI("@%s, i(%d) mFormat(%d) mSize(%d)", __FUNCTION__, i, mFormat, mSize);
}
LOGI("@%s, mDataPtr:%p, mSize:%d", __FUNCTION__, mDataPtr, mSize);
if (!mSize) {
LOGE("ERROR @%s: Failed to GetPlaneSize, it's 0", __FUNCTION__);
return UNKNOWN_ERROR;
}
mLocked = true;
return NO_ERROR;
}
status_t CameraBuffer::lock()
{
HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH);
status_t status;
int lockMode;
if (!mInit) {
LOGE("@%s: Error: Cannot lock now this buffer, not initialized", __FUNCTION__);
return INVALID_OPERATION;
}
if (mType != BUF_TYPE_HANDLE) {
mLocked = true;
return NO_ERROR;
}
if (mLocked) {
LOGE("@%s: Error: Cannot lock buffer from stream(%d), already locked",
__FUNCTION__,mOwner->seqNo());
return INVALID_OPERATION;
}
lockMode = mUsage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK |
GRALLOC_USAGE_HW_CAMERA_MASK);
if (!lockMode) {
LOGW("@%s:trying to lock a buffer with no flags", __FUNCTION__);
return INVALID_OPERATION;
}
status = lock(lockMode);
if (status != NO_ERROR) {
mUserBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
}
return status;
}
status_t CameraBuffer::unlock()
{
HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH);
if (mLocked && mType != BUF_TYPE_HANDLE) {
mLocked = false;
return NO_ERROR;
}
if (mLocked) {
LOGI("@%s, mHandle:%p, mFormat:%d", __FUNCTION__, mHandle, mFormat);
int ret = mGbmBufferManager->Unlock(mHandle);
if (ret) {
LOGE("@%s: call Unlock fail, mHandle:%p, ret:%d", __FUNCTION__, mHandle, ret);
return UNKNOWN_ERROR;
}
mLocked = false;
return NO_ERROR;
}
LOGW("@%s:trying to unlock a buffer that is not locked", __FUNCTION__);
return INVALID_OPERATION;
}
void CameraBuffer::dump()
{
if (mInit) {
LOGI("Buffer dump: handle %p: locked :%d: dataPtr:%p",
(void*)&mHandle, mLocked, mDataPtr);
} else {
LOGI("Buffer dump: Buffer not initialized");
}
}
void CameraBuffer::dumpImage(const int type, const char *name)
{
if (CC_UNLIKELY(LogHelper::isDumpTypeEnable(type))) {
dumpImage(name);
}
}
void CameraBuffer::dumpImage(const char *name)
{
if (mLocked) {
dumpImage(mDataPtr, mSize, mWidth, mHeight, name);
} else {
status_t status = lock();
CheckError((status != OK), VOID_VALUE, "failed to lock dump buffer");
dumpImage(mDataPtr, mSize, mWidth, mHeight, name);
unlock();
}
}
void CameraBuffer::dumpImage(const void *data, const int size, int width, int height,
const char *name)
{
static unsigned int count = 0;
count++;
if (gDumpInterval > 1) {
if (count % gDumpInterval != 0) {
return;
}
}
// one example for the file name: /tmp/dump_1920x1080_00000346_PREVIEW_0
std::string fileName;
std::string dumpPrefix = "dump_";
char dumpSuffix[100] = {};
snprintf(dumpSuffix, sizeof(dumpSuffix),
"%dx%d_%08u_%s_%d", width, height, count, name, mRequestID);
fileName = std::string(gDumpPath) + dumpPrefix + std::string(dumpSuffix);
LOGI("%s filename is %s", __FUNCTION__, fileName.data());
FILE *fp = fopen (fileName.data(), "w+");
if (fp == nullptr) {
LOGE("open file failed");
return;
}
if ((fwrite(data, size, 1, fp)) != 1)
LOGW("Error or short count writing %d bytes to %s", size, fileName.data());
fclose (fp);
// always leave the latest gDumpCount "dump_xxx" files
if (gDumpCount <= 0) {
return;
}
// read the "dump_xxx" files name into vector
std::vector<std::string> fileNames;
DIR* dir = opendir(gDumpPath);
CheckError(dir == nullptr, VOID_VALUE, "@%s, call opendir() fail", __FUNCTION__);
struct dirent* dp = nullptr;
while ((dp = readdir(dir)) != nullptr) {
char* ret = strstr(dp->d_name, dumpPrefix.c_str());
if (ret) {
fileNames.push_back(dp->d_name);
}
}
closedir(dir);
// remove the old files when the file number is > gDumpCount
if (fileNames.size() > gDumpCount) {
std::sort(fileNames.begin(), fileNames.end());
for (size_t i = 0; i < (fileNames.size() - gDumpCount); ++i) {
std::string fullName = gDumpPath + fileNames[i];
remove(fullName.c_str());
}
}
}
status_t CameraBuffer::captureDone(std::shared_ptr<CameraBuffer> buffer, bool signalFence) {
if(!mOwner) {
// stream is NULL in the case: rawPath + CAMERA_DUMP_RAW
// because the buf is the input mmap buffer for we set the
// RawUnit buffer type as kPostProcBufTypePre in postpipeline
LOGW("@%s : The buffer %p belong to none stream", __FUNCTION__, this);
return OK;
}
if(signalFence) {
switch (mOwner->getStreamType()) {
case STREAM_PREVIEW:
LOGD("@%s : Preview buffer signaled for req %d", __FUNCTION__, mRequestID);
dumpImage(CAMERA_DUMP_PREVIEW, "PREVIEW");
break;
case STREAM_CAPTURE:
LOGD("@%s : Capture buffer signaled for req %d", __FUNCTION__, mRequestID);
dumpImage(CAMERA_DUMP_JPEG, ".jpg");
break;
case STREAM_VIDEO:
LOGD("@%s : Video buffer signaled for req %d", __FUNCTION__, mRequestID);
dumpImage(CAMERA_DUMP_VIDEO, "VIDEO");
break;
case STREAM_ZSL:
LOGD("@%s : Zsl buffer signaled for req %d", __FUNCTION__, mRequestID);
dumpImage(CAMERA_DUMP_ZSL, "ZSL");
break;
default :
LOGW("%s:%d: Not support the stream type, is a bug, fix me", __FUNCTION__, __LINE__);
break;
}
unlock();
deinit();
fenceInc();
fenceInfo();
}
if(captureDoned) {
return OK;
}
mOwner->captureDone(buffer);
captureDoned = true;
return OK;
}
/**
* Utility methods to allocate CameraBuffers from HEAP or Gfx memory
*/
namespace MemoryUtils {
/**
* Allocates the memory needed to store the image described by the parameters
* passed during construction
*/
std::shared_ptr<CameraBuffer>
allocateHeapBuffer(int w,
int h,
int s,
int v4l2Fmt,
int cameraId,
int dataSizeOverride)
{
HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH);
void *dataPtr;
int dataSize = dataSizeOverride ? dataSizeOverride : frameSize(v4l2Fmt, s, h);
LOGI("@%s, dataSize:%d", __FUNCTION__, dataSize);
int ret = posix_memalign(&dataPtr, sysconf(_SC_PAGESIZE), dataSize);
if (dataPtr == nullptr || ret != 0) {
LOGE("Could not allocate heap camera buffer of size %d", dataSize);
return nullptr;
}
return std::shared_ptr<CameraBuffer>(new CameraBuffer(w, h, s, v4l2Fmt, dataPtr, cameraId, dataSizeOverride));
}
/**
* Allocates internal GBM buffer
*/
std::shared_ptr<CameraBuffer>
allocateHandleBuffer(int w,
int h,
int gfxFmt,
int usage)
{
HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH);
PERFORMANCE_ATRACE_NAME_SNPRINTF("Allocate One Buf %dx%d", w, h);
arc::CameraBufferManager* bufManager = arc::CameraBufferManager::GetInstance();
buffer_handle_t handle;
uint32_t stride = 0;
LOGI("%s, [wxh] = [%dx%d], format 0x%x, usage 0x%x",
__FUNCTION__, w, h, gfxFmt, usage);
int ret = bufManager->Allocate(w, h, gfxFmt, usage, arc::GRALLOC, &handle, &stride);
LOGI("Allocate handle:%p", &handle);
if (ret != 0) {
LOGE("Allocate handle failed! %d", ret);
return nullptr;
}
std::shared_ptr<CameraBuffer> buffer(new CameraBuffer());
camera3_stream_t stream;
CLEAR(stream);
stream.width = w;
stream.height = h;
stream.format = gfxFmt;
stream.usage = usage;
ret = buffer->init(&stream, handle);
if (ret != NO_ERROR) {
// buffer handle will free in CameraBuffer destructure function
return nullptr;
}
return buffer;
}
#if defined(TARGET_RK3588)
#define MAX_CAMERA_INSTANCES 6
#else
#define MAX_CAMERA_INSTANCES 4
#endif
// preAllocate buffer pool
SharedItemPool<CameraBuffer> *PreAllocateBufferPool[MAX_CAMERA_INSTANCES];
status_t
creatHandlerBufferPool(int cameraId,
int w,
int h,
int gfxFmt,
int usage,
int nums)
{
HAL_TRACE_CALL(CAM_GLBL_DBG_ERR);
PERFORMANCE_ATRACE_NAME_SNPRINTF("PreBufPool %dx%d %d", w, h, nums);
arc::CameraBufferManager* bufManager = arc::CameraBufferManager::GetInstance();
buffer_handle_t handle;
status_t ret;
uint32_t stride = 0;
CheckError(cameraId >= MAX_CAMERA_INSTANCES, UNKNOWN_ERROR,
"@%s, invaild cameraId: %d", __FUNCTION__, cameraId);
char BufPoolName[64];
snprintf(BufPoolName, 64, "%s-%d", "PreAllocateBufferPool", cameraId);
PreAllocateBufferPool[cameraId] = new SharedItemPool<CameraBuffer>(BufPoolName);
PreAllocateBufferPool[cameraId]->init(nums);
LOGI("%s, [wxh] = [%dx%d], format 0x%x, usage 0x%x, nums %d",
__FUNCTION__, w, h, gfxFmt, usage, nums);
for (int i = 0; i < nums; ++i) {
ret = bufManager->Allocate(w, h, gfxFmt, usage, arc::GRALLOC, &handle, &stride);
LOGI("Allocate handle:%p", handle);
if (ret != 0) {
LOGE("Allocate handle failed! %d", ret);
return ret;
}
std::shared_ptr<CameraBuffer> buffer = nullptr;
PreAllocateBufferPool[cameraId]->acquireItem(buffer);
camera3_stream_t stream;
CLEAR(stream);
stream.width = w;
stream.height = h;
stream.format = gfxFmt;
stream.usage = usage;
ret = buffer->init(&stream, handle);
}
return ret;
}
void destroyHandleBufferPool(int cameraId) {
LOGD("@%s : cameraId:%d", __FUNCTION__, cameraId);
CheckError(cameraId >= MAX_CAMERA_INSTANCES, ,
"@%s, invaild cameraId: %d", __FUNCTION__, cameraId);
if (PreAllocateBufferPool[cameraId])
delete PreAllocateBufferPool[cameraId];
PreAllocateBufferPool[cameraId] = NULL;
}
std::shared_ptr<CameraBuffer> acquireOneBuffer(int cameraId, int w, int h, bool allocate) {
status_t ret;
std::shared_ptr<CameraBuffer> buffer = nullptr;
PreAllocateBufferPool[cameraId]->acquireItem(buffer);
if(allocate && buffer.get() == nullptr) {
buffer = MemoryUtils::allocateHandleBuffer(w, h, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
GRALLOC_USAGE_SW_READ_OFTEN |
GRALLOC_USAGE_HW_CAMERA_WRITE|
RK_GRALLOC_USAGE_SPECIFY_STRIDE|
#ifdef GRALLOC_USAGE_RGA_ACCESS
RK_GRALLOC_USAGE_RGA_ACCESS|
#endif
/* TODO: same as the temp solution in RKISP1CameraHw.cpp configStreams func
* add GRALLOC_USAGE_HW_VIDEO_ENCODER is a temp patch for gpu bug:
* gpu cant alloc a nv12 buffer when format is
* HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED. Need gpu provide a patch */
GRALLOC_USAGE_HW_VIDEO_ENCODER);
CheckError((buffer.get() == nullptr), nullptr, "@%s : No memeory, failed allocate buffer",
__FUNCTION__);
LOGW("@%s : shortage of internal buffer, allocate a new one ", __FUNCTION__);
return buffer;
}
// reuse the Camerabuffer, just change the stream width and height
if (buffer.get() != nullptr)
buffer->reConfig(w, h);
return buffer;
}
std::shared_ptr<CameraBuffer> acquireOneBufferWithNoCache(int cameraId, int w, int h, bool allocate) {
status_t ret;
std::shared_ptr<CameraBuffer> buffer = nullptr;
//PreAllocateBufferPool[cameraId]->acquireItem(buffer);
if(allocate && buffer.get() == nullptr) {
buffer = MemoryUtils::allocateHandleBuffer(w, h, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
GRALLOC_USAGE_HW_CAMERA_WRITE|GRALLOC_USAGE_HW_CAMERA_READ|
RK_GRALLOC_USAGE_SPECIFY_STRIDE|
#ifdef GRALLOC_USAGE_RGA_ACCESS
RK_GRALLOC_USAGE_RGA_ACCESS|
#endif
/* TODO: same as the temp solution in RKISP1CameraHw.cpp configStreams func
* add GRALLOC_USAGE_HW_VIDEO_ENCODER is a temp patch for gpu bug:
* gpu cant alloc a nv12 buffer when format is
* HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED. Need gpu provide a patch */
GRALLOC_USAGE_HW_VIDEO_ENCODER);
CheckError((buffer.get() == nullptr), nullptr, "@%s : No memeory, failed allocate buffer",
__FUNCTION__);
LOGW("@%s : shortage of internal buffer, allocate a new one ", __FUNCTION__);
return buffer;
}
// reuse the Camerabuffer, just change the stream width and height
if (buffer.get() != nullptr)
buffer->reConfig(w, h);
return buffer;
}
} // namespace MemoryUtils
} /* namespace camera2 */
} /* namespace android */