赞
踩
和你一起终身学习,这里是程序员Android
经典好文推荐,通过阅读本文,您将收获以下知识点:
一、选择feature和配置feature table
二、 挂载算法
三、自定义metadata
四、APP调用算法
五、结语
多帧降噪算法(MFNR)是一种很常见的多帧算法,在MTK已预置的feature中有MTK_FEATURE_MFNR和TP_FEATURE_MFNR。因此,我们可以对号入座,不用再额外添加feature。这里我们是第三方算法,所以我们选择TP_FEATURE_MFNR。
确定了feature为TP_FEATURE_MFNR后,我们还需要将其添加到feature table中:
- diff --git a/vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/mtk/mtk_scenario_mgr.cpp b/vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/mtk/mtk_scenario_mgr.cpp
- index f14ff8a6e2..38365e0602 100755
- --- a/vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/mtk/mtk_scenario_mgr.cpp
- +++ b/vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/mtk/mtk_scenario_mgr.cpp
- @@ -106,6 +106,7 @@ using namespace NSCam::v3::pipeline::policy::scenariomgr;
- #define MTK_FEATURE_COMBINATION_TP_VSDOF_MFNR (MTK_FEATURE_MFNR | MTK_FEATURE_NR| MTK_FEATURE_ABF| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB| TP_FEATURE_VSDOF| TP_FEATURE_WATERMARK)
- #define MTK_FEATURE_COMBINATION_TP_FUSION (NO_FEATURE_NORMAL | MTK_FEATURE_NR| MTK_FEATURE_ABF| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB| TP_FEATURE_FUSION| TP_FEATURE_WATERMARK)
- #define MTK_FEATURE_COMBINATION_TP_PUREBOKEH (NO_FEATURE_NORMAL | MTK_FEATURE_NR| MTK_FEATURE_ABF| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB| TP_FEATURE_PUREBOKEH| TP_FEATURE_WATERMARK)
- +#define MTK_FEATURE_COMBINATION_TP_MFNR (TP_FEATURE_MFNR | MTK_FEATURE_NR| MTK_FEATURE_ABF| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB| MTK_FEATURE_MFNR)
-
- // streaming feature combination (TODO: it should be refined by streaming scenario feature)
- #define MTK_FEATURE_COMBINATION_VIDEO_NORMAL (MTK_FEATURE_FB|TP_FEATURE_FB|TP_FEATURE_WATERMARK)
- @@ -136,6 +137,7 @@ const std::vector<std::unordered_map<int32_t, ScenarioFeatures>> gMtkScenarioFe
- ADD_CAMERA_FEATURE_SET(TP_FEATURE_HDR, MTK_FEATURE_COMBINATION_HDR)
- ADD_CAMERA_FEATURE_SET(MTK_FEATURE_AINR, MTK_FEATURE_COMBINATION_AINR)
- ADD_CAMERA_FEATURE_SET(MTK_FEATURE_MFNR, MTK_FEATURE_COMBINATION_MFNR)
- + ADD_CAMERA_FEATURE_SET(TP_FEATURE_MFNR, MTK_FEATURE_COMBINATION_TP_MFNR)
- ADD_CAMERA_FEATURE_SET(MTK_FEATURE_REMOSAIC, MTK_FEATURE_COMBINATION_REMOSAIC)
- ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_SINGLE)
- CAMERA_SCENARIO_END
-
注意:
MTK在Android Q(10.0)及更高版本上优化了scenario配置表的客制化,Android Q及更高版本,feature需要在:
vendor/mediatek/proprietary/custom/[platform]/hal/camera/camera_custom_feature_table.cpp中配置,[platform]是诸如mt6580,mt6763之类的。
MTK HAL3在vendor/mediatek/proprietary/hardware/mtkcam3/include/mtkcam3/3rdparty/plugin/PipelinePluginType.h 中将三方算法的挂载点大致分为以下几类:
BokehPlugin:Bokeh算法挂载点,双摄景深算法的虚化部分。
DepthPlugin:Depth算法挂载点,双摄景深算法的计算深度部分。
FusionPlugin:Depth和Bokeh放在1个算法中,即合并的双摄景深算法挂载点。
JoinPlugin:Streaming相关算法挂载点,预览算法都挂载在这里。
MultiFramePlugin:多帧算法挂载点,包括YUV与RAW,例如MFNR/HDR
RawPlugin:RAW算法挂载点,例如remosaic
YuvPlugin:Yuv单帧算法挂载点,例如美颜、广角镜头畸变校正等。
对号入座,为要集成的算法选择相应的plugin。这里是多帧算法,只能选择MultiFramePlugin。并且,一般情况下多帧算法只用于拍照,不用于预览。
为了能控制某个项目是否集成此算法,我们在device/mediateksample/[platform]/ProjectConfig.mk中添加一个宏,用于控制新接入算法的编译:
- QXT_MFNR_SUPPORT = yes
-
当某个项目不需要这个算法时,将device/mediateksample/[platform]/ProjectConfig.mk的QXT_MFNR_SUPPORT的值设为 no 就可以了。
参照vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/mtk/mfnr/MFNRImpl.cpp中实现MFNR拍照。目录结构如下:
vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/customer/cp_tp_mfnr/
├── Android.mk
├── include
│ └── mf_processor.h
├── lib
│ ├── arm64-v8a
│ │ └── libmultiframe.so
│ └── armeabi-v7a
│ └── libmultiframe.so
└── MFNRImpl.cpp
文件说明:
Android.mk中配置算法库、头文件、集成的源代码MFNRImpl.cpp文件,将它们编译成库libmtkcam.plugin.tp_mfnr,供libmtkcam_3rdparty.customer依赖调用。
libmultiframe.so实现了将连续4帧图像缩小,并拼接成一张图的功能,libmultiframe.so用来模拟需要接入的第三方多帧算法库。mf_processor.h是头文件。
MFNRImpl.cpp是集成的源代码CPP文件。
- ifeq ($(QXT_MFNR_SUPPORT),yes)
- LOCAL_PATH := $(call my-dir)
-
- include $(CLEAR_VARS)
- LOCAL_MODULE := libmultiframe
- LOCAL_SRC_FILES_32 := lib/armeabi-v7a/libmultiframe.so
- LOCAL_SRC_FILES_64 := lib/arm64-v8a/libmultiframe.so
- LOCAL_MODULE_TAGS := optional
- LOCAL_MODULE_CLASS := SHARED_LIBRARIES
- LOCAL_MODULE_SUFFIX := .so
- LOCAL_PROPRIETARY_MODULE := true
- LOCAL_MULTILIB := both
- include $(BUILD_PREBUILT)
-
- ################################################################################
- #
- ################################################################################
- include $(CLEAR_VARS)
-
- #-----------------------------------------------------------
- -include $(TOP)/$(MTK_PATH_SOURCE)/hardware/mtkcam/mtkcam.mk
-
- #-----------------------------------------------------------
- LOCAL_SRC_FILES += MFNRImpl.cpp
-
- #-----------------------------------------------------------
- LOCAL_C_INCLUDES += $(MTKCAM_C_INCLUDES)
- LOCAL_C_INCLUDES += $(TOP)/$(MTK_PATH_SOURCE)/hardware/mtkcam3/include $(MTK_PATH_SOURCE)/hardware/mtkcam/include
- LOCAL_C_INCLUDES += $(TOP)/$(MTK_PATH_COMMON)/hal/inc
- LOCAL_C_INCLUDES += $(TOP)/$(MTK_PATH_CUSTOM_PLATFORM)/hal/inc
- LOCAL_C_INCLUDES += $(TOP)/external/libyuv/files/include/
- LOCAL_C_INCLUDES += $(TOP)/$(MTK_PATH_SOURCE)/hardware/mtkcam3/3rdparty/customer/cp_tp_mfnr/include
- #
- LOCAL_C_INCLUDES += system/media/camera/include
-
- #-----------------------------------------------------------
- LOCAL_CFLAGS += $(MTKCAM_CFLAGS)
- #
-
- #-----------------------------------------------------------
- LOCAL_STATIC_LIBRARIES +=
- #
- LOCAL_WHOLE_STATIC_LIBRARIES +=
-
- #-----------------------------------------------------------
- LOCAL_SHARED_LIBRARIES += liblog
- LOCAL_SHARED_LIBRARIES += libutils
- LOCAL_SHARED_LIBRARIES += libcutils
- LOCAL_SHARED_LIBRARIES += libmtkcam_modulehelper
- LOCAL_SHARED_LIBRARIES += libmtkcam_stdutils
- LOCAL_SHARED_LIBRARIES += libmtkcam_pipeline
- LOCAL_SHARED_LIBRARIES += libmtkcam_metadata
- LOCAL_SHARED_LIBRARIES += libmtkcam_metastore
- LOCAL_SHARED_LIBRARIES += libmtkcam_streamutils
- LOCAL_SHARED_LIBRARIES += libmtkcam_imgbuf
- LOCAL_SHARED_LIBRARIES += libmtkcam_exif
- #LOCAL_SHARED_LIBRARIES += libmtkcam_3rdparty
-
- #-----------------------------------------------------------
- LOCAL_HEADER_LIBRARIES := libutils_headers liblog_headers libhardware_headers
-
- #-----------------------------------------------------------
- LOCAL_MODULE := libmtkcam.plugin.tp_mfnr
- LOCAL_PROPRIETARY_MODULE := true
- LOCAL_MODULE_OWNER := mtk
- LOCAL_MODULE_TAGS := optional
- include $(MTK_STATIC_LIBRARY)
-
- ################################################################################
- #
- ################################################################################
- include $(call all-makefiles-under,$(LOCAL_PATH))
- endif
-
- #ifndef QXT_MULTI_FRAME_H
- #define QXT_MULTI_FRAME_H
-
- class MFProcessor {
-
- public:
- virtual ~MFProcessor() {}
-
- virtual void setFrameCount(int num) = 0;
-
- virtual void setParams() = 0;
-
- virtual void addFrame(unsigned char *src, int srcWidth, int srcHeight) = 0;
-
- virtual void addFrame(unsigned char *srcY, unsigned char *srcU, unsigned char *srcV,
- int srcWidth, int srcHeight) = 0;
-
- virtual void scale(unsigned char *src, int srcWidth, int srcHeight,
- unsigned char *dst, int dstWidth, int dstHeight) = 0;
-
- virtual void process(unsigned char *output, int outputWidth, int outputHeight) = 0;
-
- virtual void process(unsigned char *outputY, unsigned char *outputU, unsigned char *outputV,
- int outputWidth, int outputHeight) = 0;
-
- static MFProcessor* createInstance(int width, int height);
- };
-
- #endif //QXT_MULTI_FRAME_H
-
头文件中的接口函数介绍:
setFrameCount:没有实际作用,用于模拟设置第三方多帧算法的帧数。因为部分第三方多帧算法在不同场景下需要的帧数可能是不同的。
setParams:也没有实际作用,用于模拟设置第三方多帧算法所需的参数。
addFrame:用于添加一帧图像数据,用于模拟第三方多帧算法添加图像数据。
process:将前面添加的4帧图像数据,缩小并拼接成一张原大小的图。
createInstance:创建接口类对象。
为了方便有兴趣的童鞋们,实现代码mf_processor_impl.cpp也一并贴上:
- #include <libyuv/scale.h>
- #include <cstring>
- #include "mf_processor.h"
-
- using namespace std;
- using namespace libyuv;
-
- class MFProcessorImpl : public MFProcessor {
- private:
- int frameCount = 4;
- int currentIndex = 0;
- unsigned char *dstBuf = nullptr;
- unsigned char *tmpBuf = nullptr;
-
- public:
- MFProcessorImpl();
-
- MFProcessorImpl(int width, int height);
-
- ~MFProcessorImpl() override;
-
- void setFrameCount(int num) override;
-
- void setParams() override;
-
- void addFrame(unsigned char *src, int srcWidth, int srcHeight) override;
-
- void addFrame(unsigned char *srcY, unsigned char *srcU, unsigned char *srcV,
- int srcWidth, int srcHeight) override;
-
- void scale(unsigned char *src, int srcWidth, int srcHeight,
- unsigned char *dst, int dstWidth, int dstHeight) override;
-
- void process(unsigned char *output, int outputWidth, int outputHeight) override;
-
- void process(unsigned char *outputY, unsigned char *outputU, unsigned char *outputV,
- int outputWidth, int outputHeight) override;
-
- static MFProcessor *createInstance(int width, int height);
- };
-
- MFProcessorImpl::MFProcessorImpl() = default;
-
- MFProcessorImpl::MFProcessorImpl(int width, int height) {
- if (dstBuf == nullptr) {
- dstBuf = new unsigned char[width * height * 3 / 2];
- }
- if (tmpBuf == nullptr) {
- tmpBuf = new unsigned char[width / 2 * height / 2 * 3 / 2];
- }
- }
-
- MFProcessorImpl::~MFProcessorImpl() {
- if (dstBuf != nullptr) {
- delete[] dstBuf;
- }
-
- if (tmpBuf != nullptr) {
- delete[] tmpBuf;
- }
- }
-
- void MFProcessorImpl::setFrameCount(int num) {
- frameCount = num;
- }
-
- void MFProcessorImpl::setParams() {
-
- }
-
- void MFProcessorImpl::addFrame(unsigned char *src, int srcWidth, int srcHeight) {
- int srcYCount = srcWidth * srcHeight;
- int srcUVCount = srcWidth * srcHeight / 4;
- int tmpWidth = srcWidth >> 1;
- int tmpHeight = srcHeight >> 1;
- int tmpYCount = tmpWidth * tmpHeight;
- int tmpUVCount = tmpWidth * tmpHeight / 4;
- //scale
- I420Scale(src, srcWidth,
- src + srcYCount, srcWidth >> 1,
- src + srcYCount + srcUVCount, srcWidth >> 1,
- srcWidth, srcHeight,
- tmpBuf, tmpWidth,
- tmpBuf + tmpYCount, tmpWidth >> 1,
- tmpBuf + tmpYCount + tmpUVCount, tmpWidth >> 1,
- tmpWidth, tmpHeight,
- kFilterNone);
-
- //merge
- unsigned char *pDstY;
- unsigned char *pTmpY;
- for (int i = 0; i < tmpHeight; i++) {
- pTmpY = tmpBuf + i * tmpWidth;
- if (currentIndex == 0) {
- pDstY = dstBuf + i * srcWidth;
- } else if (currentIndex == 1) {
- pDstY = dstBuf + i * srcWidth + tmpWidth;
- } else if (currentIndex == 2) {
- pDstY = dstBuf + (i + tmpHeight) * srcWidth;
- } else {
- pDstY = dstBuf + (i + tmpHeight) * srcWidth + tmpWidth;
- }
- memcpy(pDstY, pTmpY, tmpWidth);
- }
-
- int uvHeight = tmpHeight / 2;
- int uvWidth = tmpWidth / 2;
- unsigned char *pDstU;
- unsigned char *pDstV;
- unsigned char *pTmpU;
- unsigned char *pTmpV;
- for (int i = 0; i < uvHeight; i++) {
- pTmpU = tmpBuf + tmpYCount + uvWidth * i;
- pTmpV = tmpBuf + tmpYCount + tmpUVCount + uvWidth * i;
- if (currentIndex == 0) {
- pDstU = dstBuf + srcYCount + i * tmpWidth;
- pDstV = dstBuf + srcYCount + srcUVCount + i * tmpWidth;
- } else if (currentIndex == 1) {
- pDstU = dstBuf + srcYCount + i * tmpWidth + uvWidth;
- pDstV = dstBuf + srcYCount + srcUVCount + i * tmpWidth + uvWidth;
- } else if (currentIndex == 2) {
- pDstU = dstBuf + srcYCount + (i + uvHeight) * tmpWidth;
- pDstV = dstBuf + srcYCount + srcUVCount + (i + uvHeight) * tmpWidth;
- } else {
- pDstU = dstBuf + srcYCount + (i + uvHeight) * tmpWidth + uvWidth;
- pDstV = dstBuf + srcYCount + srcUVCount + (i + uvHeight) * tmpWidth + uvWidth;
- }
- memcpy(pDstU, pTmpU, uvWidth);
- memcpy(pDstV, pTmpV, uvWidth);
- }
- if (currentIndex < frameCount) currentIndex++;
- }
-
- void MFProcessorImpl::addFrame(unsigned char *srcY, unsigned char *srcU, unsigned char *srcV,
- int srcWidth, int srcHeight) {
- int srcYCount = srcWidth * srcHeight;
- int srcUVCount = srcWidth * srcHeight / 4;
- int tmpWidth = srcWidth >> 1;
- int tmpHeight = srcHeight >> 1;
- int tmpYCount = tmpWidth * tmpHeight;
- int tmpUVCount = tmpWidth * tmpHeight / 4;
- //scale
- I420Scale(srcY, srcWidth,
- srcU, srcWidth >> 1,
- srcV, srcWidth >> 1,
- srcWidth, srcHeight,
- tmpBuf, tmpWidth,
- tmpBuf + tmpYCount, tmpWidth >> 1,
- tmpBuf + tmpYCount + tmpUVCount, tmpWidth >> 1,
- tmpWidth, tmpHeight,
- kFilterNone);
-
- //merge
- unsigned char *pDstY;
- unsigned char *pTmpY;
- for (int i = 0; i < tmpHeight; i++) {
- pTmpY = tmpBuf + i * tmpWidth;
- if (currentIndex == 0) {
- pDstY = dstBuf + i * srcWidth;
- } else if (currentIndex == 1) {
- pDstY = dstBuf + i * srcWidth + tmpWidth;
- } else if (currentIndex == 2) {
- pDstY = dstBuf + (i + tmpHeight) * srcWidth;
- } else {
- pDstY = dstBuf + (i + tmpHeight) * srcWidth + tmpWidth;
- }
- memcpy(pDstY, pTmpY, tmpWidth);
- }
-
- int uvHeight = tmpHeight / 2;
- int uvWidth = tmpWidth / 2;
- unsigned char *pDstU;
- unsigned char *pDstV;
- unsigned char *pTmpU;
- unsigned char *pTmpV;
- for (int i = 0; i < uvHeight; i++) {
- pTmpU = tmpBuf + tmpYCount + uvWidth * i;
- pTmpV = tmpBuf + tmpYCount + tmpUVCount + uvWidth * i;
- if (currentIndex == 0) {
- pDstU = dstBuf + srcYCount + i * tmpWidth;
- pDstV = dstBuf + srcYCount + srcUVCount + i * tmpWidth;
- } else if (currentIndex == 1) {
- pDstU = dstBuf + srcYCount + i * tmpWidth + uvWidth;
- pDstV = dstBuf + srcYCount + srcUVCount + i * tmpWidth + uvWidth;
- } else if (currentIndex == 2) {
- pDstU = dstBuf + srcYCount + (i + uvHeight) * tmpWidth;
- pDstV = dstBuf + srcYCount + srcUVCount + (i + uvHeight) * tmpWidth;
- } else {
- pDstU = dstBuf + srcYCount + (i + uvHeight) * tmpWidth + uvWidth;
- pDstV = dstBuf + srcYCount + srcUVCount + (i + uvHeight) * tmpWidth + uvWidth;
- }
- memcpy(pDstU, pTmpU, uvWidth);
- memcpy(pDstV, pTmpV, uvWidth);
- }
- if (currentIndex < frameCount) currentIndex++;
- }
-
- void MFProcessorImpl::scale(unsigned char *src, int srcWidth, int srcHeight,
- unsigned char *dst, int dstWidth, int dstHeight) {
- I420Scale(src, srcWidth,//Y
- src + srcWidth * srcHeight, srcWidth >> 1,//U
- src + srcWidth * srcHeight * 5 / 4, srcWidth >> 1,//V
- srcWidth, srcHeight,
- dst, dstWidth,//Y
- dst + dstWidth * dstHeight, dstWidth >> 1,//U
- dst + dstWidth * dstHeight * 5 / 4, dstWidth >> 1,//V
- dstWidth, dstHeight,
- kFilterNone);
- }
-
- void MFProcessorImpl::process(unsigned char *output, int outputWidth, int outputHeight) {
- memcpy(output, dstBuf, outputWidth * outputHeight * 3 / 2);
- currentIndex = 0;
- }
-
- void MFProcessorImpl::process(unsigned char *outputY, unsigned char *outputU, unsigned char *outputV,
- int outputWidth, int outputHeight) {
- int yCount = outputWidth * outputHeight;
- int uvCount = yCount / 4;
- memcpy(outputY, dstBuf, yCount);
- memcpy(outputU, dstBuf + yCount, uvCount);
- memcpy(outputV, dstBuf + yCount + uvCount, uvCount);
- currentIndex = 0;
- }
-
- MFProcessor* MFProcessor::createInstance(int width, int height) {
- return new MFProcessorImpl(width, height);
- }
-
- #ifdef LOG_TAG
- #undef LOG_TAG
- #endif // LOG_TAG
- #define LOG_TAG "MFNRProvider"
- static const char *__CALLERNAME__ = LOG_TAG;
-
- //
- #include <mtkcam/utils/std/Log.h>
- //
- #include <stdlib.h>
- #include <utils/Errors.h>
- #include <utils/List.h>
- #include <utils/RefBase.h>
- #include <sstream>
- #include <unordered_map> // std::unordered_map
- //
- #include <mtkcam/utils/metadata/client/mtk_metadata_tag.h>
- #include <mtkcam/utils/metadata/hal/mtk_platform_metadata_tag.h>
- //zHDR
- #include <mtkcam/utils/hw/HwInfoHelper.h> // NSCamHw::HwInfoHelper
- #include <mtkcam3/feature/utils/FeatureProfileHelper.h> //ProfileParam
- #include <mtkcam/drv/IHalSensor.h>
- //
- #include <mtkcam/utils/imgbuf/IIonImageBufferHeap.h>
- //
- #include <mtkcam/utils/std/Format.h>
- #include <mtkcam/utils/std/Time.h>
- //
- #include <mtkcam3/pipeline/hwnode/NodeId.h>
- //
- #include <mtkcam/utils/metastore/IMetadataProvider.h>
- #include <mtkcam/utils/metastore/ITemplateRequest.h>
- #include <mtkcam/utils/metastore/IMetadataProvider.h>
- #include <mtkcam3/3rdparty/plugin/PipelinePlugin.h>
- #include <mtkcam3/3rdparty/plugin/PipelinePluginType.h>
- //
- #include <isp_tuning/isp_tuning.h> //EIspProfile_T, EOperMode_*
-
- //
- #include <custom_metadata/custom_metadata_tag.h>
-
- //
- #include <libyuv.h>
- #include <mf_processor.h>
-
- using namespace NSCam;
- using namespace android;
- using namespace std;
- using namespace NSCam::NSPipelinePlugin;
- using namespace NSIspTuning;
- /******************************************************************************
- *
- ******************************************************************************/
- #define MY_LOGV(fmt, arg...) CAM_LOGV("(%d)[%s] " fmt, ::gettid(), __FUNCTION__, ##arg)
- #define MY_LOGD(fmt, arg...) CAM_LOGD("(%d)[%s] " fmt, ::gettid(), __FUNCTION__, ##arg)
- #define MY_LOGI(fmt, arg...) CAM_LOGI("(%d)[%s] " fmt, ::gettid(), __FUNCTION__, ##arg)
- #define MY_LOGW(fmt, arg...) CAM_LOGW("(%d)[%s] " fmt, ::gettid(), __FUNCTION__, ##arg)
- #define MY_LOGE(fmt, arg...) CAM_LOGE("(%d)[%s] " fmt, ::gettid(), __FUNCTION__, ##arg)
- //
- #define MY_LOGV_IF(cond, ...) do { if ( (cond) ) { MY_LOGV(__VA_ARGS__); } }while(0)
- #define MY_LOGD_IF(cond, ...) do { if ( (cond) ) { MY_LOGD(__VA_ARGS__); } }while(0)
- #define MY_LOGI_IF(cond, ...) do { if ( (cond) ) { MY_LOGI(__VA_ARGS__); } }while(0)
- #define MY_LOGW_IF(cond, ...) do { if ( (cond) ) { MY_LOGW(__VA_ARGS__); } }while(0)
- #define MY_LOGE_IF(cond, ...) do { if ( (cond) ) { MY_LOGE(__VA_ARGS__); } }while(0)
- //
- #define ASSERT(cond, msg) do { if (!(cond)) { printf("Failed: %s\n", msg); return; } }while(0)
-
- #define __DEBUG // enable debug
-
- #ifdef __DEBUG
- #include <memory>
- #define FUNCTION_SCOPE \
- auto __scope_logger__ = [](char const* f)->std::shared_ptr<const char>{ \
- CAM_LOGD("(%d)[%s] + ", ::gettid(), f); \
- return std::shared_ptr<const char>(f, [](char const* p){CAM_LOGD("(%d)[%s] -", ::gettid(), p);}); \
- }(__FUNCTION__)
- #else
- #define FUNCTION_SCOPE
- #endif
-
- template <typename T>
- inline MBOOL
- tryGetMetadata(
- IMetadata* pMetadata,
- MUINT32 const tag,
- T & rVal
- )
- {
- if (pMetadata == NULL) {
- MY_LOGW("pMetadata == NULL");
- return MFALSE;
- }
-
- IMetadata::IEntry entry = pMetadata->entryFor(tag);
- if (!entry.isEmpty()) {
- rVal = entry.itemAt(0, Type2Type<T>());
- return MTRUE;
- }
- return MFALSE;
- }
-
- #define MFNR_FRAME_COUNT 4
- /******************************************************************************
- *
- ******************************************************************************/
- class MFNRProviderImpl : public MultiFramePlugin::IProvider {
- typedef MultiFramePlugin::Property Property;
- typedef MultiFramePlugin::Selection Selection;
- typedef MultiFramePlugin::Request::Ptr RequestPtr;
- typedef MultiFramePlugin::RequestCallback::Ptr RequestCallbackPtr;
-
- public:
-
- virtual void set(MINT32 iOpenId, MINT32 iOpenId2) {
- MY_LOGD("set openId:%d openId2:%d", iOpenId, iOpenId2);
- mOpenId = iOpenId;
- }
-
- virtual const Property& property() {
- FUNCTION_SCOPE;
- static Property prop;
- static bool inited;
-
- if (!inited) {
- prop.mName = "TP_MFNR";
- prop.mFeatures = TP_FEATURE_MFNR;
- prop.mThumbnailTiming = eTiming_P2;
- prop.mPriority = ePriority_Highest;
- prop.mZsdBufferMaxNum = 8; // maximum frames requirement
- prop.mNeedRrzoBuffer = MTRUE; // rrzo requirement for BSS
- inited = MTRUE;
- }
- return prop;
- };
-
- virtual MERROR negotiate(Selection& sel) {
- FUNCTION_SCOPE;
-
- IMetadata* appInMeta = sel.mIMetadataApp.getControl().get();
- tryGetMetadata<MINT32>(appInMeta, QXT_FEATURE_MFNR, mEnable);
- MY_LOGD("mEnable: %d", mEnable);
- if (!mEnable) {
- MY_LOGD("Force off TP_MFNR shot");
- return BAD_VALUE;
- }
-
- sel.mRequestCount = MFNR_FRAME_COUNT;
-
- MY_LOGD("mRequestCount=%d", sel.mRequestCount);
- sel.mIBufferFull
- .setRequired(MTRUE)
- .addAcceptedFormat(eImgFmt_I420) // I420 first
- .addAcceptedFormat(eImgFmt_YV12)
- .addAcceptedFormat(eImgFmt_NV21)
- .addAcceptedFormat(eImgFmt_NV12)
- .addAcceptedSize(eImgSize_Full);
- //sel.mIBufferSpecified.setRequired(MTRUE).setAlignment(16, 16);
- sel.mIMetadataDynamic.setRequired(MTRUE);
- sel.mIMetadataApp.setRequired(MTRUE);
- sel.mIMetadataHal.setRequired(MTRUE);
- if (sel.mRequestIndex == 0) {
- sel.mOBufferFull
- .setRequired(MTRUE)
- .addAcceptedFormat(eImgFmt_I420) // I420 first
- .addAcceptedFormat(eImgFmt_YV12)
- .addAcceptedFormat(eImgFmt_NV21)
- .addAcceptedFormat(eImgFmt_NV12)
- .addAcceptedSize(eImgSize_Full);
- sel.mOMetadataApp.setRequired(MTRUE);
- sel.mOMetadataHal.setRequired(MTRUE);
- } else {
- sel.mOBufferFull.setRequired(MFALSE);
- sel.mOMetadataApp.setRequired(MFALSE);
- sel.mOMetadataHal.setRequired(MFALSE);
- }
-
- return OK;
- };
-
- virtual void init() {
- FUNCTION_SCOPE;
- mDump = property_get_bool("vendor.debug.camera.mfnr.dump", 0);
- //nothing to do for MFNR
- };
-
- virtual MERROR process(RequestPtr pRequest, RequestCallbackPtr pCallback) {
- FUNCTION_SCOPE;
- MERROR ret = 0;
- // restore callback function for abort API
- if (pCallback != nullptr) {
- m_callbackprt = pCallback;
- }
- //maybe need to keep a copy in member<sp>
- IMetadata* pAppMeta = pRequest->mIMetadataApp->acquire();
- IMetadata* pHalMeta = pRequest->mIMetadataHal->acquire();
- IMetadata* pHalMetaDynamic = pRequest->mIMetadataDynamic->acquire();
- MINT32 processUniqueKey = 0;
- IImageBuffer* pInImgBuffer = NULL;
- uint32_t width = 0;
- uint32_t height = 0;
- if (!IMetadata::getEntry<MINT32>(pHalMeta, MTK_PIPELINE_UNIQUE_KEY, processUniqueKey)) {
- MY_LOGE("cannot get unique about MFNR capture");
- return BAD_VALUE;
- }
-
- if (pRequest->mIBufferFull != nullptr) {
- pInImgBuffer = pRequest->mIBufferFull->acquire();
- width = pInImgBuffer->getImgSize().w;
- height = pInImgBuffer->getImgSize().h;
- MY_LOGD("[IN] Full image VA: 0x%p, Size(%dx%d), Format: %s",
- pInImgBuffer->getBufVA(0), width, height, format2String(pInImgBuffer->getImgFormat()));
- if (mDump) {
- char path[256];
- snprintf(path, sizeof(path), "/data/vendor/camera_dump/mfnr_capture_in_%d_%dx%d.%s",
- pRequest->mRequestIndex, width, height, format2String(pInImgBuffer->getImgFormat()));
- pInImgBuffer->saveToFile(path);
- }
- }
- if (pRequest->mIBufferSpecified != nullptr) {
- IImageBuffer* pImgBuffer = pRequest->mIBufferSpecified->acquire();
- MY_LOGD("[IN] Specified image VA: 0x%p, Size(%dx%d)", pImgBuffer->getBufVA(0), pImgBuffer->getImgSize().w, pImgBuffer->getImgSize().h);
- }
- if (pRequest->mOBufferFull != nullptr) {
- mOutImgBuffer = pRequest->mOBufferFull->acquire();
- MY_LOGD("[OUT] Full image VA: 0x%p, Size(%dx%d)", mOutImgBuffer->getBufVA(0), mOutImgBuffer->getImgSize().w, mOutImgBuffer->getImgSize().h);
- }
- if (pRequest->mIMetadataDynamic != nullptr) {
- IMetadata *meta = pRequest->mIMetadataDynamic->acquire();
- if (meta != NULL)
- MY_LOGD("[IN] Dynamic metadata count: ", meta->count());
- else
- MY_LOGD("[IN] Dynamic metadata Empty");
- }
-
- MY_LOGD("frame:%d/%d, width:%d, height:%d", pRequest->mRequestIndex, pRequest->mRequestCount, width, height);
-
- if (pInImgBuffer != NULL && mOutImgBuffer != NULL) {
- uint32_t yLength = pInImgBuffer->getBufSizeInBytes(0);
- uint32_t uLength = pInImgBuffer->getBufSizeInBytes(1);
- uint32_t vLength = pInImgBuffer->getBufSizeInBytes(2);
- uint32_t yuvLength = yLength + uLength + vLength;
-
- if (pRequest->mRequestIndex == 0) {//First frame
- //When width or height changed, recreate multiFrame
- if (mLatestWidth != width || mLatestHeight != height) {
- if (mMFProcessor != NULL) {
- delete mMFProcessor;
- mMFProcessor = NULL;
- }
- mLatestWidth = width;
- mLatestHeight = height;
- }
- if (mMFProcessor == NULL) {
- MY_LOGD("create mMFProcessor %dx%d", mLatestWidth, mLatestHeight);
- mMFProcessor = MFProcessor::createInstance(mLatestWidth, mLatestHeight);
- mMFProcessor->setFrameCount(pRequest->mRequestCount);
- }
- }
-
- mMFProcessor->addFrame((uint8_t *)pInImgBuffer->getBufVA(0),
- (uint8_t *)pInImgBuffer->getBufVA(1),
- (uint8_t *)pInImgBuffer->getBufVA(2),
- mLatestWidth, mLatestHeight);
-
- if (pRequest->mRequestIndex == pRequest->mRequestCount - 1) {//Last frame
- if (mMFProcessor != NULL) {
- mMFProcessor->process((uint8_t *)mOutImgBuffer->getBufVA(0),
- (uint8_t *)mOutImgBuffer->getBufVA(1),
- (uint8_t *)mOutImgBuffer->getBufVA(2),
- mLatestWidth, mLatestHeight);
- if (mDump) {
- char path[256];
- snprintf(path, sizeof(path), "/data/vendor/camera_dump/mfnr_capture_out_%d_%dx%d.%s",
- pRequest->mRequestIndex, mOutImgBuffer->getImgSize().w, mOutImgBuffer->getImgSize().h,
- format2String(mOutImgBuffer->getImgFormat()));
- mOutImgBuffer->saveToFile(path);
- }
- } else {
- memcpy((uint8_t *)mOutImgBuffer->getBufVA(0),
- (uint8_t *)pInImgBuffer->getBufVA(0),
- pInImgBuffer->getBufSizeInBytes(0));
- memcpy((uint8_t *)mOutImgBuffer->getBufVA(1),
- (uint8_t *)pInImgBuffer->getBufVA(1),
- pInImgBuffer->getBufSizeInBytes(1));
- memcpy((uint8_t *)mOutImgBuffer->getBufVA(2),
- (uint8_t *)pInImgBuffer->getBufVA(2),
- pInImgBuffer->getBufSizeInBytes(2));
- }
- mOutImgBuffer = NULL;
- }
- }
-
- if (pRequest->mIBufferFull != nullptr) {
- pRequest->mIBufferFull->release();
- }
- if (pRequest->mIBufferSpecified != nullptr) {
- pRequest->mIBufferSpecified->release();
- }
- if (pRequest->mOBufferFull != nullptr) {
- pRequest->mOBufferFull->release();
- }
- if (pRequest->mIMetadataDynamic != nullptr) {
- pRequest->mIMetadataDynamic->release();
- }
-
- mvRequests.push_back(pRequest);
- MY_LOGD("collected request(%d/%d)", pRequest->mRequestIndex, pRequest->mRequestCount);
- if (pRequest->mRequestIndex == pRequest->mRequestCount - 1) {
- for (auto req : mvRequests) {
- MY_LOGD("callback request(%d/%d) %p", req->mRequestIndex, req->mRequestCount, pCallback.get());
- if (pCallback != nullptr) {
- pCallback->onCompleted(req, 0);
- }
- }
- mvRequests.clear();
- }
- return ret;
- };
-
- virtual void abort(vector<RequestPtr>& pRequests) {
- FUNCTION_SCOPE;
-
- bool bAbort = false;
- IMetadata *pHalMeta;
- MINT32 processUniqueKey = 0;
-
- for (auto req:pRequests) {
- bAbort = false;
- pHalMeta = req->mIMetadataHal->acquire();
- if (!IMetadata::getEntry<MINT32>(pHalMeta, MTK_PIPELINE_UNIQUE_KEY, processUniqueKey)) {
- MY_LOGW("cannot get unique about MFNR capture");
- }
-
- if (m_callbackprt != nullptr) {
- MY_LOGD("m_callbackprt is %p", m_callbackprt.get());
- /*MFNR plugin callback request to MultiFrameNode */
- for (Vector<RequestPtr>::iterator it = mvRequests.begin() ; it != mvRequests.end(); it++) {
- if ((*it) == req) {
- mvRequests.erase(it);
- m_callbackprt->onAborted(req);
- bAbort = true;
- break;
- }
- }
- } else {
- MY_LOGW("callbackptr is null");
- }
-
- if (!bAbort) {
- MY_LOGW("Desire abort request[%d] is not found", req->mRequestIndex);
- }
-
- }
- };
-
- virtual void uninit() {
- FUNCTION_SCOPE;
- if (mMFProcessor != NULL) {
- delete mMFProcessor;
- mMFProcessor = NULL;
- }
- mLatestWidth = 0;
- mLatestHeight = 0;
- };
-
- virtual ~MFNRProviderImpl() {
- FUNCTION_SCOPE;
- };
-
- const char * format2String(MINT format) {
- switch(format) {
- case NSCam::eImgFmt_RGBA8888: return "rgba";
- case NSCam::eImgFmt_RGB888: return "rgb";
- case NSCam::eImgFmt_RGB565: return "rgb565";
- case NSCam::eImgFmt_STA_BYTE: return "byte";
- case NSCam::eImgFmt_YVYU: return "yvyu";
- case NSCam::eImgFmt_UYVY: return "uyvy";
- case NSCam::eImgFmt_VYUY: return "vyuy";
- case NSCam::eImgFmt_YUY2: return "yuy2";
- case NSCam::eImgFmt_YV12: return "yv12";
- case NSCam::eImgFmt_YV16: return "yv16";
- case NSCam::eImgFmt_NV16: return "nv16";
- case NSCam::eImgFmt_NV61: return "nv61";
- case NSCam::eImgFmt_NV12: return "nv12";
- case NSCam::eImgFmt_NV21: return "nv21";
- case NSCam::eImgFmt_I420: return "i420";
- case NSCam::eImgFmt_I422: return "i422";
- case NSCam::eImgFmt_Y800: return "y800";
- case NSCam::eImgFmt_BAYER8: return "bayer8";
- case NSCam::eImgFmt_BAYER10: return "bayer10";
- case NSCam::eImgFmt_BAYER12: return "bayer12";
- case NSCam::eImgFmt_BAYER14: return "bayer14";
- case NSCam::eImgFmt_FG_BAYER8: return "fg_bayer8";
- case NSCam::eImgFmt_FG_BAYER10: return "fg_bayer10";
- case NSCam::eImgFmt_FG_BAYER12: return "fg_bayer12";
- case NSCam::eImgFmt_FG_BAYER14: return "fg_bayer14";
- default: return "unknown";
- };
- };
-
- private:
-
- MINT32 mUniqueKey;
- MINT32 mOpenId;
- MINT32 mRealIso;
- MINT32 mShutterTime;
- MBOOL mZSDMode;
- MBOOL mFlashOn;
-
- Vector<RequestPtr> mvRequests;
-
- RequestCallbackPtr m_callbackprt;
- MFProcessor* mMFProcessor = NULL;
- IImageBuffer* mOutImgBuffer = NULL;
- uint32_t mLatestWidth = 0;
- uint32_t mLatestHeight = 0;
- MINT32 mEnable = 0;
- MINT32 mDump = 0;
- // add end
- };
-
- REGISTER_PLUGIN_PROVIDER(MultiFrame, MFNRProviderImpl);
-
主要函数介绍:
在property函数中feature类型设置成TP_FEATURE_MFNR,并设置名称、优先级、最大帧数等等属性。尤其注意mNeedRrzoBuffer属性,一般情况下,多帧算法必须要设置为MTRUE。
在negotiate函数中配置算法需要的输入、输出图像的格式、尺寸。注意,多帧算法有多帧输入,但是只需要一帧输出。因此这里设置了mRequestIndex == 0时才需要mOBufferFull。也就是只有第一帧才有输入和输出,其它帧只有输入。
另外,还在negotiate函数中获取上层传下来的metadata参数,根据参数决定算法是否运行。
在process函数中接入算法。第一帧时创建算法接口类对象,然后每一帧都调用算法接口函数addFrame加入,最后一帧再调用算法接口函数process进行处理并获取输出。
最终vendor.img需要的目标共享库是libmtkcam_3rdparty.customer.so。因此,我们还需要修改Android.mk,使模块libmtkcam_3rdparty.customer依赖libmtkcam.plugin.tp_mfnr。
- diff --git a/vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/customer/Android.mk b/vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/customer/Android.mk
- index ff5763d3c2..5e5dd6524f 100755
- --- a/vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/customer/Android.mk
- +++ b/vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/customer/Android.mk
- @@ -77,6 +77,12 @@ LOCAL_SHARED_LIBRARIES += libyuv.vendor
- LOCAL_WHOLE_STATIC_LIBRARIES += libmtkcam.plugin.tp_watermark
- endif
-
- +ifeq ($(QXT_MFNR_SUPPORT), yes)
- +LOCAL_SHARED_LIBRARIES += libmultiframe
- +LOCAL_SHARED_LIBRARIES += libyuv.vendor
- +LOCAL_WHOLE_STATIC_LIBRARIES += libmtkcam.plugin.tp_mfnr
- +endif
- +
- # for app super night ev decision (experimental for customer only)
- LOCAL_WHOLE_STATIC_LIBRARIES += libmtkcam.control.customersupernightevdecision
- ################################################################################
-
一般情况下,MFNR 算法同一时间只允许运行一个。因此,需要移除 MTK 示例的 MFNR 算法。我们可以使用宏控来移除,这里就简单粗暴,直接注释掉了。
- diff --git a/vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/mtk/Android.mk b/vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/mtk/Android.mk
- index 4e2bc68dff..da98ebd0ad 100644
- --- a/vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/mtk/Android.mk
- +++ b/vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/mtk/Android.mk
- @@ -118,7 +118,7 @@ LOCAL_SHARED_LIBRARIES += libfeature.stereo.provider
-
- #-----------------------------------------------------------
- ifneq ($(strip $(MTKCAM_HAVE_MFB_SUPPORT)),0)
- -LOCAL_WHOLE_STATIC_LIBRARIES += libmtkcam.plugin.mfnr
- +#LOCAL_WHOLE_STATIC_LIBRARIES += libmtkcam.plugin.mfnr
- endif
- #4 Cell
- LOCAL_WHOLE_STATIC_LIBRARIES += libmtkcam.plugin.remosaic
-
添加metadata是为了让APP层能够通过metadata传递相应的参数给HAL层,以此来控制算法在运行时是否启用。APP层是通过CaptureRequest.Builder.set(@NonNull Key<T> key, T value)来设置参数的。由于MTK原生相机APP没有多帧降噪模式,因此,我们自定义metadata来验证集成效果。
vendor/mediatek/proprietary/hardware/mtkcam/include/mtkcam/utils/metadata/client/mtk_metadata_tag.h:
- diff --git a/vendor/mediatek/proprietary/hardware/mtkcam/include/mtkcam/utils/metadata/client/mtk_metadata_tag.h b/vendor/mediatek/proprietary/hardware/mtkcam/include/mtkcam/utils/metadata/client/mtk_metadata_tag.h
- index b020352092..714d05f350 100755
- --- a/vendor/mediatek/proprietary/hardware/mtkcam/include/mtkcam/utils/metadata/client/mtk_metadata_tag.h
- +++ b/vendor/mediatek/proprietary/hardware/mtkcam/include/mtkcam/utils/metadata/client/mtk_metadata_tag.h
- @@ -602,6 +602,7 @@ typedef enum mtk_camera_metadata_tag {
- MTK_FLASH_FEATURE_END,
-
- QXT_FEATURE_WATERMARK = QXT_FEATURE_START,
- + QXT_FEATURE_MFNR,
- QXT_FEATURE_END,
- } mtk_camera_metadata_tag_t;
-
vendor/mediatek/proprietary/hardware/mtkcam/include/mtkcam/utils/metadata/client/mtk_metadata_tag_info.inl:
- diff --git a/vendor/mediatek/proprietary/hardware/mtkcam/include/mtkcam/utils/metadata/client/mtk_metadata_tag_info.inl b/vendor/mediatek/proprietary/hardware/mtkcam/include/mtkcam/utils/metadata/client/mtk_metadata_tag_info.inl
- index 1b4fc75a0e..cba4511511 100755
- --- a/vendor/mediatek/proprietary/hardware/mtkcam/include/mtkcam/utils/metadata/client/mtk_metadata_tag_info.inl
- +++ b/vendor/mediatek/proprietary/hardware/mtkcam/include/mtkcam/utils/metadata/client/mtk_metadata_tag_info.inl
- @@ -95,6 +95,8 @@ _IMP_SECTION_INFO_(QXT_FEATURE, "com.qxt.camera")
-
- _IMP_TAG_INFO_( QXT_FEATURE_WATERMARK,
- MINT32, "watermark")
- +_IMP_TAG_INFO_( QXT_FEATURE_MFNR,
- + MINT32, "mfnr")
-
- /******************************************************************************
- *
vendor/mediatek/proprietary/hardware/mtkcam/utils/metadata/vendortag/VendorTagTable.h :
- diff --git a/vendor/mediatek/proprietary/hardware/mtkcam/utils/metadata/vendortag/VendorTagTable.h b/vendor/mediatek/proprietary/hardware/mtkcam/utils/metadata/vendortag/VendorTagTable.h
- index 33e581adfd..4f4772424d 100755
- --- a/vendor/mediatek/proprietary/hardware/mtkcam/utils/metadata/vendortag/VendorTagTable.h
- +++ b/vendor/mediatek/proprietary/hardware/mtkcam/utils/metadata/vendortag/VendorTagTable.h
- @@ -383,6 +383,8 @@ static auto& _QxtFeature_()
- sInst = {
- _TAG_(QXT_FEATURE_WATERMARK,
- "watermark", TYPE_INT32),
- + _TAG_(QXT_FEATURE_MFNR,
- + "mfnr", TYPE_INT32),
- };
- //
- return sInst;
-
vendor/mediatek/proprietary/hardware/mtkcam/utils/metastore/metadataprovider/constructStaticMetadata.cpp :
- diff --git a/vendor/mediatek/proprietary/hardware/mtkcam/utils/metastore/metadataprovider/constructStaticMetadata.cpp b/vendor/mediatek/proprietary/hardware/mtkcam/utils/metastore/metadataprovider/constructStaticMetadata.cpp
- index 591b25b162..9c3db8b1d1 100755
- --- a/vendor/mediatek/proprietary/hardware/mtkcam/utils/metastore/metadataprovider/constructStaticMetadata.cpp
- +++ b/vendor/mediatek/proprietary/hardware/mtkcam/utils/metastore/metadataprovider/constructStaticMetadata.cpp
- @@ -583,10 +583,12 @@ updateData(IMetadata &rMetadata)
- {
- IMetadata::IEntry qxtAvailRequestEntry = rMetadata.entryFor(MTK_REQUEST_AVAILABLE_REQUEST_KEYS);
- qxtAvailRequestEntry.push_back(QXT_FEATURE_WATERMARK , Type2Type< MINT32 >());
- + qxtAvailRequestEntry.push_back(QXT_FEATURE_MFNR , Type2Type< MINT32 >());
- rMetadata.update(qxtAvailRequestEntry.tag(), qxtAvailRequestEntry);
-
- IMetadata::IEntry qxtAvailSessionEntry = rMetadata.entryFor(MTK_REQUEST_AVAILABLE_SESSION_KEYS);
- qxtAvailSessionEntry.push_back(QXT_FEATURE_WATERMARK , Type2Type< MINT32 >());
- + qxtAvailSessionEntry.push_back(QXT_FEATURE_MFNR , Type2Type< MINT32 >());
- rMetadata.update(qxtAvailSessionEntry.tag(), qxtAvailSessionEntry);
- }
- #endif
- @@ -605,7 +607,7 @@ updateData(IMetadata &rMetadata)
- // to store manual update metadata for sensor driver.
- IMetadata::IEntry availCharactsEntry = rMetadata.entryFor(MTK_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS);
- availCharactsEntry.push_back(MTK_MULTI_CAM_FEATURE_SENSOR_MANUAL_UPDATED , Type2Type< MINT32 >());
- - rMetadata.update(availCharactsEntry.tag(), availCharactsEntry);
- + rMetadata.update(availCharactsEntry.tag(), availCharactsEntry);
- }
- if(physicIdsList.size() > 1)
- {
-
前面这些步骤完成之后,集成工作就基本完成了。我们需要重新编译一下系统源码,为节约时间,也可以只编译vendor.img。
验证算法我们无需再重新写APP,继续使用《MTK HAL算法集成之单帧算法》中的APP代码,只需要将KEY_WATERMARK的值改为"com.qxt.camera.mfnr"即可。为样机刷入系统整包或者vendor.img,开机后,安装demo验证。我们来拍一张看看效果:
image
可以看到,集成后,这个模拟MFNR的多帧算法已经将连续的4帧图像缩小并拼接成一张图了。
真正的多帧算法要复杂一些,例如,MFNR算法可能会根据曝光值决定是否启用,光线好就不启用,光线差就启用;HDR算法,可能会要求获取连续几帧不同曝光的图像。可能还会有智能的场景检测等等。但是不管怎么变,多帧算法大体上的集成步骤都是类似的。如果遇到不同的需求,可能要根据需求灵活调整一下代码。
原文链接:https://www.jianshu.com/p/f0b57072ea74
友情推荐:
至此,本篇已结束。转载网络的文章,小编觉得很优秀,欢迎点击阅读原文,支持原创作者,如有侵权,恳请联系小编删除,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!
点个在看,方便您使用时快速查找!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。