| /* |
| * 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; |
| } |