blob: 6c56e0bfa14238aa8a94c17c4644d90242d3f6d6 [file] [log] [blame]
/*
* Copyright (C) 2019 MediaTek Inc.
*
* 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 "MtkCam/GraphicImageBufferHeap"
//
#include "BaseImageBufferHeap.h"
#include <camera_buffer_handle.h>
#include <cros-camera/camera_buffer_manager.h>
#include <linux/videodev2.h>
#include <memory>
#include <mtkcam/utils/gralloc/IGrallocHelper.h>
#include <mtkcam/utils/imgbuf/IGraphicImageBufferHeap.h>
#include <vector>
using NSCam::GrallocStaticInfo;
using NSCam::IGrallocHelper;
using NSCam::IGraphicImageBufferHeap;
using NSCam::NSImageBufferHeap::BaseImageBufferHeap;
/******************************************************************************
* Image Buffer Heap.
******************************************************************************/
namespace {
class GraphicImageBufferHeap
: public IGraphicImageBufferHeap,
public NSCam::NSImageBufferHeap::BaseImageBufferHeap {
friend class IGraphicImageBufferHeap;
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// IGraphicImageBufferHeap Interface.
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public: //// Accessors.
virtual buffer_handle_t getBufferHandle() const { return *mpBufferHandle; }
virtual buffer_handle_t* getBufferHandlePtr() const { return mpBufferHandle; }
virtual MINT getAcquireFence() const { return mAcquireFence; }
virtual MVOID setAcquireFence(MINT fence) { mAcquireFence = fence; }
virtual MINT getReleaseFence() const { return mReleaseFence; }
virtual MVOID setReleaseFence(MINT fence) { mReleaseFence = fence; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BaseImageBufferHeap Interface.
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
protected: ////
virtual char const* impGetMagicName() const { return magicName(); }
virtual HeapInfoVect_t const& impGetHeapInfo() const { return mvHeapInfo; }
virtual MBOOL impInit(BufInfoVect_t const& rvBufInfo);
virtual MBOOL impUninit();
virtual MBOOL impReconfig(BufInfoVect_t const& rvBufInfo) { return MFALSE; }
public: ////
virtual MBOOL impLockBuf(char const* szCallerName,
MINT usage,
BufInfoVect_t const& rvBufInfo);
virtual MBOOL impUnlockBuf(char const* szCallerName,
MINT usage,
BufInfoVect_t const& rvBufInfo);
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Definitions.
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
protected: //// Heap Info.
typedef HeapInfo MyHeapInfo;
typedef std::vector<std::shared_ptr<MyHeapInfo> > MyHeapInfoVect_t;
protected: //// Buffer Info.
typedef std::vector<std::shared_ptr<BufInfo> > MyBufInfoVect_t;
struct BufferParams {
int width = 0;
int height = 0;
int stride = 0;
int format = 0;
int usage = 0;
};
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Implementations.
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
protected
: ////
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Instantiation.
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public: //// Destructor/Constructors.
/**
* Disallowed to directly delete a raw pointer.
*/
virtual ~GraphicImageBufferHeap();
GraphicImageBufferHeap(char const* szCallerName,
buffer_handle_t* pBufferHandle,
const BufferParams& rBufParams,
MINT const acquire_fence,
MINT const release_fence);
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Data Members.
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
protected: ////
MyHeapInfoVect_t mvHeapInfo;
MyBufInfoVect_t mvBufInfo;
protected: ////
buffer_handle_t* mpBufferHandle;
BufferParams mBufferParams;
int mAcquireFence;
int mReleaseFence;
};
}; // namespace
/******************************************************************************
*
******************************************************************************/
static bool validate_camera3_stream_buffer(
camera3_stream_buffer const* stream_buffer) {
if (!stream_buffer) {
CAM_LOGE("camera3_stream_buffer: NULL");
return false;
}
//
if (!stream_buffer->stream) {
CAM_LOGE("camera3_stream_buffer: NULL stream");
return false;
}
//
if (!stream_buffer->buffer) {
CAM_LOGE("camera3_stream_buffer: NULL buffer");
return false;
}
//
if (!*stream_buffer->buffer) {
CAM_LOGE("camera3_stream_buffer: NULL *buffer");
return false;
}
///
return true;
}
/******************************************************************************
*
******************************************************************************/
std::shared_ptr<IGraphicImageBufferHeap> IGraphicImageBufferHeap::create(
char const* szCallerName, camera3_stream_buffer const* stream_buffer) {
if (!validate_camera3_stream_buffer(stream_buffer)) {
return nullptr;
}
//
GrallocStaticInfo staticInfo;
MERROR status = IGrallocHelper::singleton()->query(
*stream_buffer->buffer, stream_buffer->stream->usage, &staticInfo);
if (OK != status) {
CAM_LOGE(
"cannot query the real format from buffer_handle_t - status:%d(%s)",
status, ::strerror(-status));
return nullptr;
}
//
GraphicImageBufferHeap::BufferParams rBufParams = {
.width = static_cast<int>(stream_buffer->stream->width),
.height = static_cast<int>(stream_buffer->stream->height),
.stride = 0,
.format = static_cast<int>(staticInfo.format),
.usage = static_cast<int>(stream_buffer->stream->usage),
};
//
std::shared_ptr<GraphicImageBufferHeap> pHeap = nullptr;
pHeap = std::make_shared<GraphicImageBufferHeap>(
szCallerName, stream_buffer->buffer, rBufParams,
stream_buffer->acquire_fence, stream_buffer->release_fence);
if (!pHeap) {
CAM_LOGE("Fail to new a heap");
return nullptr;
}
MSize const imgSize(rBufParams.width, rBufParams.height);
int format = staticInfo.format;
if (!pHeap->onCreate(std::dynamic_pointer_cast<BaseImageBufferHeap>(pHeap),
imgSize, format, 0, /*enableLog*/ false)) {
CAM_LOGE("onCreate fail");
return nullptr;
}
//
return pHeap;
}
/******************************************************************************
*
******************************************************************************/
GraphicImageBufferHeap::GraphicImageBufferHeap(char const* szCallerName,
buffer_handle_t* pBufferHandle,
const BufferParams& rBufParams,
int const acquire_fence,
int const release_fence)
: BaseImageBufferHeap(szCallerName),
mpBufferHandle(pBufferHandle),
mBufferParams(rBufParams),
mAcquireFence(acquire_fence),
mReleaseFence(release_fence) {}
GraphicImageBufferHeap::~GraphicImageBufferHeap() {
impUninit();
}
/******************************************************************************
*
******************************************************************************/
MBOOL
GraphicImageBufferHeap::impInit(BufInfoVect_t const& rvBufInfo) {
GrallocStaticInfo staticInfo;
IGrallocHelper* const pGrallocHelper = IGrallocHelper::singleton();
//
MERROR status = OK;
//
status = pGrallocHelper->query(getBufferHandle(), mBufferParams.usage,
&staticInfo);
if (OK != status) {
MY_LOGE("cannot query the real format from buffer_handle_t - status:%d[%s]",
status, ::strerror(status));
return false;
}
//
mvHeapInfo.reserve(getPlaneCount());
mvBufInfo.reserve(getPlaneCount());
//
for (int i = 0; i < getPlaneCount(); i++) {
std::shared_ptr<MyHeapInfo> pHeapInfo = std::make_shared<MyHeapInfo>();
mvHeapInfo.push_back(pHeapInfo);
pHeapInfo->heapID = getBufferHandle()->data[i];
//
std::shared_ptr<BufInfo> pBufInfo = std::make_shared<BufInfo>();
mvBufInfo.push_back(pBufInfo);
pBufInfo->stridesInBytes = staticInfo.planes[i].rowStrideInBytes;
pBufInfo->sizeInBytes = staticInfo.planes[i].sizeInBytes;
pBufInfo->offsetInBytes = staticInfo.planes[i].offsetInBytes;
//
rvBufInfo[i]->stridesInBytes = pBufInfo->stridesInBytes;
rvBufInfo[i]->sizeInBytes = pBufInfo->sizeInBytes;
rvBufInfo[i]->offsetInBytes = pBufInfo->offsetInBytes;
}
//
return true;
}
/******************************************************************************
*
******************************************************************************/
MBOOL
GraphicImageBufferHeap::impUninit() {
mvBufInfo.clear();
mvHeapInfo.clear();
return MTRUE;
}
/******************************************************************************
*
******************************************************************************/
MBOOL
GraphicImageBufferHeap::impLockBuf(char const* szCallerName,
int usage,
BufInfoVect_t const& rvBufInfo) {
cros::CameraBufferManager* bufManager =
cros::CameraBufferManager::GetInstance();
int v4l2Fmt = bufManager->GetV4L2PixelFormat(getBufferHandle());
uint32_t planeNum = bufManager->GetNumPlanes(getBufferHandle());
int ret = 0;
if (planeNum == 1) {
void* data = nullptr;
ret =
(mBufferParams.format == HAL_PIXEL_FORMAT_BLOB)
? bufManager->Lock(getBufferHandle(), 0, 0, 0,
mBufferParams.width * mBufferParams.height, 1,
&data)
: bufManager->Lock(getBufferHandle(), 0, 0, 0, mBufferParams.width,
mBufferParams.height, &data);
if (ret) {
MY_LOGE("@%s: call Lock fail, mHandle:%p", __FUNCTION__, mpBufferHandle);
return MFALSE;
}
//
MINTPTR va = reinterpret_cast<MINTPTR>(data);
for (size_t i = 0; i < mvBufInfo.size(); i++) {
rvBufInfo[i]->va = va;
va += mvBufInfo[i]->sizeInBytes;
}
} else if (planeNum > 1) {
struct android_ycbcr ycbrData;
ret = bufManager->LockYCbCr(getBufferHandle(), 0, 0, 0, mBufferParams.width,
mBufferParams.height, &ycbrData);
if (ret) {
MY_LOGE("@%s: call LockYCbCr fail, mHandle:%p", __FUNCTION__,
getBufferHandle());
return MFALSE;
}
rvBufInfo[0]->va = reinterpret_cast<MINTPTR>(ycbrData.y);
if (planeNum == 2) {
switch (v4l2Fmt) {
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_NV12M:
rvBufInfo[1]->va = reinterpret_cast<MINTPTR>(ycbrData.cb);
break;
default:
MY_LOGE("Unsupported semi-planar format: %s",
FormatToString(v4l2Fmt).c_str());
}
} else { // num_planes == 3
switch (v4l2Fmt) {
case V4L2_PIX_FMT_YVU420:
case V4L2_PIX_FMT_YVU420M:
rvBufInfo[1]->va = reinterpret_cast<MINTPTR>(ycbrData.cr);
rvBufInfo[2]->va = reinterpret_cast<MINTPTR>(ycbrData.cb);
break;
default:
MY_LOGE("Unsupported planar format: %s",
FormatToString(v4l2Fmt).c_str());
}
}
} else {
MY_LOGE("ERROR @%s: planeNum is 0", __FUNCTION__);
return MFALSE;
}
//
return MTRUE;
}
/******************************************************************************
*
******************************************************************************/
MBOOL
GraphicImageBufferHeap::impUnlockBuf(char const* szCallerName,
MINT usage,
BufInfoVect_t const& rvBufInfo) {
for (size_t i = 0; i < getPlaneCount(); i++) {
rvBufInfo[i]->va = 0;
rvBufInfo[i]->pa = 0;
}
//
cros::CameraBufferManager* bufManager =
cros::CameraBufferManager::GetInstance();
bufManager->Unlock(getBufferHandle());
//
return MTRUE;
}