blob: b97fd1ea3c8dbfba8794365ad5900175cfb98a13 [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.
*/
#ifndef CAMERA_HAL_MEDIATEK_MTKCAM_PIPELINE_HWNODE_MYUTILS_H_
#define CAMERA_HAL_MEDIATEK_MTKCAM_PIPELINE_HWNODE_MYUTILS_H_
#include <algorithm>
#include <isp_tuning/isp_tuning.h> // EIspProfile_*
#include <memory>
#include <mtkcam/def/common.h>
#include <mtkcam/utils/std/Trace.h>
#include <mtkcam/utils/std/Log.h>
#include <mtkcam/utils/std/Sync.h>
#include <mtkcam/utils/imgbuf/IImageBuffer.h>
#include <mtkcam/aaa/IHal3A.h>
#include <mtkcam/drv/IHalSensor.h> // MAKE_HalSensorList
#include <sys/prctl.h>
#include <sys/resource.h>
#include <vector>
/******************************************************************************
*
******************************************************************************/
namespace NSCam {
namespace v3 {
// utilities for crop
inline MINT32 div_round(MINT32 const numerator, MINT32 const denominator) {
return ((numerator < 0) ^ (denominator < 0))
? ((numerator - denominator / 2) / denominator)
: ((numerator + denominator / 2) / denominator);
}
struct vector_f { // vector with floating point
MPoint p;
MPoint pf;
explicit vector_f(MPoint const& rP = MPoint(), MPoint const& rPf = MPoint())
: p(rP), pf(rPf) {}
};
struct simpleTransform {
// just support translation than scale, not a general formulation
// translation
MPoint tarOrigin;
// scale
MSize oldScale;
MSize newScale;
simpleTransform(MPoint rOrigin = MPoint(),
MSize rOldScale = MSize(),
MSize rNewScale = MSize())
: tarOrigin(rOrigin), oldScale(rOldScale), newScale(rNewScale) {}
};
// transform MPoint
inline MPoint transform(simpleTransform const& trans, MPoint const& p) {
return MPoint(
div_round((p.x - trans.tarOrigin.x) * trans.newScale.w, trans.oldScale.w),
div_round((p.y - trans.tarOrigin.y) * trans.newScale.h,
trans.oldScale.h));
}
inline MPointF transform(simpleTransform const& trans, MPointF const& p) {
return MPointF(
((p.x - trans.tarOrigin.x) * trans.newScale.w / trans.oldScale.w),
((p.y - trans.tarOrigin.y) * trans.newScale.h / trans.oldScale.h));
}
inline MPoint inv_transform(simpleTransform const& trans, MPoint const& p) {
return MPoint(
div_round(p.x * trans.oldScale.w, trans.newScale.w) + trans.tarOrigin.x,
div_round(p.y * trans.oldScale.h, trans.newScale.h) + trans.tarOrigin.y);
}
inline int int_floor(float x) {
int i = static_cast<int>(x);
return i - (i > x);
}
// transform vector_f
inline vector_f transform(simpleTransform const& trans, vector_f const& p) {
MFLOAT const x = (p.p.x + (p.pf.x / (MFLOAT)(1u << 31))) * trans.newScale.w /
trans.oldScale.w;
MFLOAT const y = (p.p.y + (p.pf.y / (MFLOAT)(1u << 31))) * trans.newScale.h /
trans.oldScale.h;
int const x_int = int_floor(x);
int const y_int = int_floor(y);
return vector_f(MPoint(x_int, y_int),
MPoint((x - x_int) * (1u << 31), (y - y_int) * (1u << 31)));
}
inline vector_f inv_transform(simpleTransform const& trans, vector_f const& p) {
MFLOAT const x = (p.p.x + (p.pf.x / (MFLOAT)(1u << 31))) * trans.oldScale.w /
trans.newScale.w;
MFLOAT const y = (p.p.y + (p.pf.y / (MFLOAT)(1u << 31))) * trans.oldScale.h /
trans.newScale.h;
int const x_int = int_floor(x);
int const y_int = int_floor(y);
return vector_f(MPoint(x_int, y_int),
MPoint((x - x_int) * (1u << 31), (y - y_int) * (1u << 31)));
}
// transform MSize
inline MSize transform(simpleTransform const& trans, MSize const& s) {
return MSize(div_round(s.w * trans.newScale.w, trans.oldScale.w),
div_round(s.h * trans.newScale.h, trans.oldScale.h));
}
inline MSizeF transform(simpleTransform const& trans, MSizeF const& s) {
return MSizeF((s.w * trans.newScale.w / trans.oldScale.w),
(s.h * trans.newScale.h / trans.oldScale.h));
}
inline MSize inv_transform(simpleTransform const& trans, MSize const& s) {
return MSize(div_round(s.w * trans.oldScale.w, trans.newScale.w),
div_round(s.h * trans.oldScale.h, trans.newScale.h));
}
// transform MRect
inline MRect transform(simpleTransform const& trans, MRect const& r) {
return MRect(transform(trans, r.p), transform(trans, r.s));
}
inline MRectF transform(simpleTransform const& trans, MRectF const& r) {
return MRectF(transform(trans, r.p), transform(trans, r.s));
}
inline MRect inv_transform(simpleTransform const& trans, MRect const& r) {
return MRect(inv_transform(trans, r.p), inv_transform(trans, r.s));
}
/******************************************************************************
* Metadata Access
******************************************************************************/
template <typename T>
inline MBOOL tryGetMetadata(IMetadata const* pMetadata,
MUINT32 const tag,
T* rVal) {
if (pMetadata == nullptr) {
CAM_LOGW("pMetadata == NULL");
return MFALSE;
}
//
IMetadata::IEntry entry = pMetadata->entryFor(tag);
if (!entry.isEmpty()) {
*rVal = entry.itemAt(0, Type2Type<T>());
return MTRUE;
}
//
return MFALSE;
}
template <typename T>
inline MBOOL trySetMetadata(IMetadata* pMetadata,
MUINT32 const tag,
T const& val) {
if (pMetadata == nullptr) {
CAM_LOGW("pMetadata == NULL");
return MFALSE;
}
//
IMetadata::IEntry entry(tag);
entry.push_back(val, Type2Type<T>());
if (0 == pMetadata->update(tag, entry)) {
return MTRUE;
}
//
return MFALSE;
}
/******************************************************************************
* Simulate HAL 3A.
******************************************************************************/
/******************************************************************************
* Hardware Related
******************************************************************************/
inline MBOOL isPostProcRawSupported() {
MBOOL bSupport = MTRUE;
#if (MTKCAM_HW_NODE_WITH_LEGACY_SUPPORT > 0)
bSupport = MFALSE;
#endif
return bSupport;
}
/******************************************************************************
* Opaque Reprocessing Utility
******************************************************************************/
#define MAX_METADATA_SIZE (200000)
class OpaqueReprocUtil {
private:
typedef struct opaque_reproc_info_t {
MINT8 aligned_byte;
MSize raw_size;
MINT raw_format;
size_t stride_in_bytes;
size_t payload_offset;
size_t payload_length;
size_t app_meta_offset;
size_t app_meta_length;
size_t hal_meta_offset;
size_t hal_meta_length;
size_t lcso_image_offset;
size_t lcso_image_length;
MVOID dump() {
CAM_LOGD(
"[opaque] aligned_byte(0x%x) raw_size(%d,%d) raw_format(0x%x) "
"stride_in_bytes(%zu) "
"payload(%zu-%zu) app_meta(%zu-%zu) hal_meta(%zu-%zu)"
"lcso_image(%zu-%zu)",
aligned_byte, raw_size.w, raw_size.h, raw_format, stride_in_bytes,
payload_offset, payload_length, app_meta_offset, app_meta_length,
hal_meta_offset, hal_meta_length, lcso_image_offset,
lcso_image_length);
}
} opaque_reproc_info_t;
public:
static MERROR setOpaqueInfoToHeap(
std::shared_ptr<IImageBufferHeap> const& pImageBufferHeap,
MSize const rawSize,
MINT const rawFormat,
size_t const rawStrideInBytes,
size_t const rawSizeInBytes) {
size_t infoOffset = (ssize_t)pImageBufferHeap->getBufSizeInBytes(0) -
sizeof(opaque_reproc_info_t);
if (infoOffset < rawSizeInBytes) {
return -EINVAL;
}
MINTPTR ptrOpaqueBuf = (MINTPTR)pImageBufferHeap->getBufVA(0);
opaque_reproc_info_t* pInfo =
reinterpret_cast<opaque_reproc_info_t*>(ptrOpaqueBuf + infoOffset);
pInfo->aligned_byte = 0x00;
pInfo->raw_size = rawSize;
pInfo->raw_format = rawFormat;
pInfo->stride_in_bytes = rawStrideInBytes;
pInfo->payload_offset = rawSizeInBytes;
pInfo->payload_length = infoOffset - rawSizeInBytes;
pInfo->app_meta_offset = 0;
pInfo->app_meta_length = 0;
pInfo->hal_meta_offset = 0;
pInfo->hal_meta_length = 0;
pInfo->lcso_image_offset = 0;
pInfo->lcso_image_length = 0;
return 0;
}
static MERROR getImageBufferFromHeap(
std::shared_ptr<IImageBufferHeap> pImageBufferHeap,
std::shared_ptr<IImageBuffer>* rpImageBuffer) {
size_t infoOffset =
pImageBufferHeap->getBufSizeInBytes(0) - sizeof(opaque_reproc_info_t);
MINTPTR ptrOpaqueBuf = (MINTPTR)pImageBufferHeap->getBufVA(0);
opaque_reproc_info_t* pInfo =
reinterpret_cast<opaque_reproc_info_t*>(ptrOpaqueBuf + infoOffset);
if (pInfo->aligned_byte != 0x00) {
return NO_INIT;
}
size_t strideInBytes[3]{pInfo->stride_in_bytes, 0, 0};
*rpImageBuffer = pImageBufferHeap->createImageBuffer_FromBlobHeap(
0, pInfo->raw_format, pInfo->raw_size, strideInBytes);
return 0;
}
static MERROR setAppMetadataToHeap(
std::shared_ptr<IImageBufferHeap> const& pImageBufferHeap,
IMetadata* appMeta) {
size_t infoOffset =
pImageBufferHeap->getBufSizeInBytes(0) - sizeof(opaque_reproc_info_t);
MINTPTR ptrOpaqueBuf = (MINTPTR)pImageBufferHeap->getBufVA(0);
opaque_reproc_info_t* pInfo =
reinterpret_cast<opaque_reproc_info_t*>(ptrOpaqueBuf + infoOffset);
if (pInfo->aligned_byte != 0x00) {
return NO_INIT;
} else if (pInfo->app_meta_length != 0) {
return ALREADY_EXISTS;
}
// calculate the offset of app meta where hal meta/lcso is probably empty
pInfo->app_meta_offset = pInfo->payload_offset + pInfo->hal_meta_length +
pInfo->lcso_image_length;
void* pAppMetaBuf =
reinterpret_cast<void*>(ptrOpaqueBuf + pInfo->app_meta_offset);
MINT32 max_size = pInfo->payload_length - pInfo->hal_meta_length -
pInfo->lcso_image_length;
ssize_t ret = appMeta->flatten(pAppMetaBuf, max_size);
if (ret < 0) {
CAM_LOGE("[opaque] oversized payload: ret=%zd, hal=%zu, lcso=%zu", ret,
pInfo->hal_meta_length, pInfo->lcso_image_length);
return ret;
}
pInfo->app_meta_length = ret;
return 0;
}
static MERROR setHalMetadataToHeap(
std::shared_ptr<IImageBufferHeap> const& pImageBufferHeap,
IMetadata* halMeta) {
size_t infoOffset =
pImageBufferHeap->getBufSizeInBytes(0) - sizeof(opaque_reproc_info_t);
MINTPTR ptrOpaqueBuf = (MINTPTR)pImageBufferHeap->getBufVA(0);
opaque_reproc_info_t* pInfo =
reinterpret_cast<opaque_reproc_info_t*>(ptrOpaqueBuf + infoOffset);
if (pInfo->aligned_byte != 0x00) {
return NO_INIT;
} else if (pInfo->hal_meta_length != 0) {
return ALREADY_EXISTS;
}
// calculate the offset of app meta where app meta/lcso is probably empty
pInfo->hal_meta_offset = pInfo->payload_offset + pInfo->app_meta_length +
pInfo->lcso_image_length;
void* pHalMetaBuf =
reinterpret_cast<void*>(ptrOpaqueBuf + pInfo->hal_meta_offset);
MINT32 max_size = pInfo->payload_length - pInfo->app_meta_length -
pInfo->lcso_image_length;
ssize_t ret = halMeta->flatten(pHalMetaBuf, max_size);
if (ret < 0) {
CAM_LOGE("[opaque] oversized payload: ret =%zd, app=%zu, lcso=%zu", ret,
pInfo->app_meta_length, pInfo->lcso_image_length);
return ret;
}
pInfo->hal_meta_length = ret;
return 0;
}
static MERROR setLcsoImageToHeap(
std::shared_ptr<IImageBufferHeap> const& pImageBufferHeap,
std::shared_ptr<IImageBuffer> pLcsoBuffer) {
size_t infoOffset =
pImageBufferHeap->getBufSizeInBytes(0) - sizeof(opaque_reproc_info_t);
MINTPTR ptrOpaqueBuf = (MINTPTR)pImageBufferHeap->getBufVA(0);
opaque_reproc_info_t* pInfo =
reinterpret_cast<opaque_reproc_info_t*>(ptrOpaqueBuf + infoOffset);
if (pInfo->aligned_byte != 0x00) {
return NO_INIT;
} else if (pInfo->lcso_image_length != 0) {
return ALREADY_EXISTS;
}
// calculate the offset of lcso image where app/hal meta is probably empty
pInfo->lcso_image_offset =
pInfo->payload_offset + pInfo->app_meta_length + pInfo->hal_meta_length;
void* pLsocBuf =
reinterpret_cast<void*>(ptrOpaqueBuf + pInfo->lcso_image_offset);
MINT32 max_size =
pInfo->payload_length - pInfo->app_meta_length - pInfo->hal_meta_length;
if (pLcsoBuffer->getBufSizeInBytes(0) > max_size) {
CAM_LOGE("[opaque] oversized payload: lcso=%zu, app=%zu, hal=%zu",
pLcsoBuffer->getBufSizeInBytes(0), pInfo->app_meta_length,
pInfo->hal_meta_length);
return BAD_VALUE;
}
memcpy(pLsocBuf, reinterpret_cast<void*>(pLcsoBuffer->getBufVA(0)),
pLcsoBuffer->getBufSizeInBytes(0));
pInfo->lcso_image_length = pLcsoBuffer->getBufSizeInBytes(0);
return 0;
}
static MERROR getAppMetadataFromHeap(
std::shared_ptr<IImageBufferHeap> const& pImageBufferHeap,
IMetadata* appMeta) {
size_t infoOffset =
pImageBufferHeap->getBufSizeInBytes(0) - sizeof(opaque_reproc_info_t);
MINTPTR ptrOpaqueBuf = (MINTPTR)pImageBufferHeap->getBufVA(0);
opaque_reproc_info_t* pInfo =
reinterpret_cast<opaque_reproc_info_t*>(ptrOpaqueBuf + infoOffset);
if (pInfo->aligned_byte != 0x00) {
return NO_INIT;
}
void* pAppMetaBuf =
reinterpret_cast<void*>(ptrOpaqueBuf + pInfo->app_meta_offset);
ssize_t ret = appMeta->unflatten(pAppMetaBuf, pInfo->app_meta_length);
CAM_LOGD_IF(0, "[opaque] app meta unflatten from size: %zd", ret);
if (ret < 0) {
return ret;
}
return 0;
}
static MERROR getHalMetadataFromHeap(
std::shared_ptr<IImageBufferHeap> const& pImageBufferHeap,
IMetadata* halMeta) {
size_t infoOffset =
pImageBufferHeap->getBufSizeInBytes(0) - sizeof(opaque_reproc_info_t);
MINTPTR ptrOpaqueBuf = (MINTPTR)pImageBufferHeap->getBufVA(0);
opaque_reproc_info_t* pInfo =
reinterpret_cast<opaque_reproc_info_t*>(ptrOpaqueBuf + infoOffset);
if (pInfo->aligned_byte != 0x00) {
return NO_INIT;
}
void* pHalMetaBuf =
reinterpret_cast<void*>(ptrOpaqueBuf + pInfo->hal_meta_offset);
ssize_t ret = halMeta->unflatten(pHalMetaBuf, pInfo->hal_meta_length);
CAM_LOGD_IF(0, "[opaque] hal meta unflatten from size: %zd", ret);
if (ret < 0) {
return ret;
}
return 0;
}
static MERROR getLcsoImageFromHeap(
std::shared_ptr<IImageBufferHeap> const& pImageBufferHeap,
std::shared_ptr<IImageBuffer> pLcsoBuffer) {
size_t infoOffset =
pImageBufferHeap->getBufSizeInBytes(0) - sizeof(opaque_reproc_info_t);
MINTPTR ptrOpaqueBuf = (MINTPTR)pImageBufferHeap->getBufVA(0);
opaque_reproc_info_t* pInfo =
reinterpret_cast<opaque_reproc_info_t*>(ptrOpaqueBuf + infoOffset);
if (pInfo->aligned_byte != 0x00) {
return NO_INIT;
}
void* pLsocBuf =
reinterpret_cast<void*>(ptrOpaqueBuf + pInfo->lcso_image_offset);
if (pLcsoBuffer->getBufSizeInBytes(0) != pInfo->lcso_image_length) {
CAM_LOGE("[opaque] invalid lcso size: %zu - %zu",
pLcsoBuffer->getBufSizeInBytes(0), pInfo->lcso_image_length);
return BAD_VALUE;
}
memcpy(reinterpret_cast<void*>(pLcsoBuffer->getBufVA(0)), pLsocBuf,
pInfo->lcso_image_length);
return 0;
}
};
}; // namespace v3
}; // namespace NSCam
#endif // CAMERA_HAL_MEDIATEK_MTKCAM_PIPELINE_HWNODE_MYUTILS_H_