Android11.0(R) HAL 相机集成水印算法+多帧算法

文摘 无标签 2021-09-19 阅读:1153

一、写在前面

上网经常看到一些好文章,除了收藏之外,顺手一会照着搞一搞。这次看到 qiuxintai 写的

MTK HAL算法集成之单帧算法

MTK HAL算法集成之多帧算法

有点东西,写的很详细,

适合来一遍,文章是基于MTK 9.0 的,大差不差。我就基于最新的 11 搞了。

二、准备工作

qiuxintai 文章中并没有提供 libwatermark.so watermark.rgba

libmultiframe.so 这几个关键的东西,所以我们要先把这几个东西集齐才能召唤神龙。

经过一顿翻看,好在 qiuxintai 还是留了点线索,去他 github 中提取这几个关键的东西。

https://github.com/qiuxintai/Watermark/

https://github.com/qiuxintai/YUV420Converter/

虽然你找到了这些原材料,好戏才刚刚开始,你需要将原材料提取成可放到 aosp 中编译的格式且不报错还是

有一点麻烦的。这期间停滞了好几天,也算是补充了不少 so 编译相关的知识。 那么开始干吧!

三、提取精华

新建 AS 工程,就叫 jnidemo 吧,从 YUV420Converter 中提取 cpp 文件夹下所有文件到 jnidemo 中

从 qiuxintai 多帧文章中提取 mf_processor_impl.cpp

从 Watermark 中提取 watermark.cpp 并进行改造

整合后的 jnidemo 链接

这里说一下 CMakeLists.txt 含义

cmake_minimum_required(VERSION 3.4.1)

#引入头文件依赖编译

include_directories(${CMAKE_SOURCE_DIR}/include)

find_library(log-lib log)

#编译 libNativeUtils.so

add_library(

        NativeUtils

        SHARED

        native.cpp

        native_utils.cpp

)

target_link_libraries(NativeUtils ${log-lib})

#引入第三方libopencv_java3.so 编译 opencv3

add_library(opencv3 SHARED IMPORTED)

set_target_properties(

        opencv3

        PROPERTIES

        IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libopencv_java3.so

)

#编译 libOpencvUtils.so 并链接刚刚 opencv3

add_library(

        OpencvUtils

        SHARED

        opencv.cpp

        opencv_utils.cpp

)

target_link_libraries(OpencvUtils opencv3 ${log-lib})

#引入第三方libyuv.so 编译 libyuv

add_library(libyuv SHARED IMPORTED)

set_target_properties(

        libyuv

        PROPERTIES IMPORTED_LOCATION

        ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libyuv.so

)

#编译 libLibyuvUtils.so 并链接刚刚 libyuv

add_library(

        LibyuvUtils

        SHARED

        libyuv.cpp

        libyuv_utils.cpp

)

target_link_libraries(LibyuvUtils libyuv ${log-lib})

#编译 libmultiframe.so 并链接刚刚 libyuv

add_library(

        multiframe

        SHARED

        mf_processor_impl.cpp

)

target_link_libraries(multiframe libyuv ${log-lib})

#编译 libwatermark.so 

add_library(

        watermark

        SHARED

        watermark.cpp

)

target_link_libraries(watermark ${log-lib})



build.gradle 中配置使用 cmake 编译 so,并制定 so 对应平台

 defaultConfig {

....

 /*externalNativeBuild {

            ndkBuild {

                path "src/main/jni/Android.mk"

            }

        }*/

        externalNativeBuild {

            cmake {

                cppFlags ""

            }

        }

        ndk {

            abiFilters  'arm64-v8a', 'armeabi-v7a'

        }

    }

    externalNativeBuild {

        cmake {

            path "src/main/cpp/CMakeLists.txt"

            version "3.10.2"

        }

    }

使用CMake引入第三方so库及头文件

AS使用ndkbuild创建cpp工程记录

ubuntu16.04 安装交叉编译工具aarch64-linux-gnu-gcc/g++

项目 build 成功后, so 位于 jnidemobuildintermediatescmakereleaseobjarm64-v8a

问题一

vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/customer/tp_watermark/lib/arm64-v8a/libwatermark.so: error: DT_NEEDED "libstdc++.so" is not specified in shared_libs.

vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/customer/tp_watermark/lib/arm64-v8a/libwatermark.so: note:

vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/customer/tp_watermark/lib/arm64-v8a/libwatermark.so: note: Fix suggestions:

vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/customer/tp_watermark/lib/arm64-v8a/libwatermark.so: note:   Android.bp: shared_libs: ["libc", "libdl", "libm", "libstdc++"],

vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/customer/tp_watermark/lib/arm64-v8a/libwatermark.so: note:   Android.mk: LOCAL_SHARED_LIBRARIES := libc libdl libm libstdc++

vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/customer/tp_watermark/lib/arm64-v8a/libwatermark.so: note:

vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/customer/tp_watermark/lib/arm64-v8a/libwatermark.so: note: If the fix above doesn't work, bypass this check with:

vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/customer/tp_watermark/lib/arm64-v8a/libwatermark.so: note:   Android.bp: check_elf_files: false,

vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/customer/tp_watermark/lib/arm64-v8a/libwatermark.so: note:   Android.mk: LOCAL_CHECK_ELF_FILES := false

[  5% 661/11941] target Strip: vendor.mediatek.hardware.camera.bgservice@1.1-impl

libwatermark.so 有问题,最开始用的 ndk 编译 so 文件,扔到源码里就出现上面奇怪的错误,一开始并没有想到用

cmake 编译,而是去 Ubuntu 下使用 ndk 再次编译,结果还是一样的。

四、注入灵魂(水印算法+多帧算法)

接下来就是跟着 qiuxintai 步骤来

4.1 添加自定义feature

添加新feature,我们选择添加一个自定义feature:TP_FEATURE_WATERMARK

vendor/mediatek/proprietary/hardware/mtkcam3/include/mtkcam3/3rdparty/customer/customer_feature_type.h

@@ -61,6 +61,7 @@ enum eFeatureIndexCustomer {

     TP_FEATURE_RELIGHTING   = 1ULL << 45,

     TP_FEATURE_ASYNC_ASD    = 1ULL << 46,

     TP_FEATURE_ZOOM_FUSION  = 1ULL << 47,   // used by zoom scenario

+    TP_FEATURE_WATERMARK    = 1ULL << 48,   //cczheng

     // TODO: reserve for customer feature index (bit 32-63)

 };

vendor/mediatek/proprietary/hardware/mtkcam3/feature/core/featurePipe/capture/CaptureFeature_Common.cpp

@@ -592,6 +592,7 @@ const char* FeatID2Name(FeatureID_T fid)

     case FID_RELIGHTING_3RD_PARTY:  return "relighting_3rd_party";

     case FID_AINR_YHDR:             return "ainr_yhdr";

     case FID_AIHDR:                 return "aihdr";

+    case FID_WATERMARK_3RD_PARTY:   return "watermark_3rd_party";//cczheng

     default:                        return "unknown";

     };

vendor/mediatek/proprietary/hardware/mtkcam3/feature/core/featurePipe/capture/nodes/YUVNode.cpp

@@ -619,6 +619,9 @@ MBOOL YUVNode::onInit()

             featId = FID_RELIGHTING_3RD_PARTY;

         else if(rProperty.mFeatures & MTK_FEATURE_YHDR_FOR_AINR)

             featId = FID_AINR_YHDR;

+        else if (rProperty.mFeatures & TP_FEATURE_WATERMARK)

+            featId = FID_WATERMARK_3RD_PARTY;//cczheng

+ 

         if (featId != NULL_FEATURE) {

             MY_LOGD_IF(mLogLevel, "%s finds plugin:%s, priority:%d",

vendor/mediatek/proprietary/hardware/mtkcam3/include/mtkcam3/feature/featurePipe/ICaptureFeaturePipe.h

@@ -191,6 +191,7 @@ enum CaptureFeatureFeatureID {

     FID_RELIGHTING_3RD_PARTY,

     FID_AINR_YHDR,

     FID_AIHDR,

+    FID_WATERMARK_3RD_PARTY,

     NUM_OF_FEATURE,

     NULL_FEATURE = 0xFF,

 };

vendor/mediatek/proprietary/hardware/mtkcam3/pipeline/hwnode/p2/P2_CaptureProcessor.cpp

@@ -487,6 +487,8 @@ MBOOL CaptureProcessor::onEnque(const sp<P2FrameRequest> &pP2FrameRequest)

                     pCapRequest->addFeature(FID_HFG);

                 if (feature & MTK_FEATURE_DCE)

                     pCapRequest->addFeature(FID_DCE);

+                if (feature & TP_FEATURE_WATERMARK)

+                    pCapRequest->addFeature(FID_WATERMARK_3RD_PARTY);//cczheng

                 if (feature & MTK_FEATURE_AINR_YUV)

                     pCapRequest->addFeature(FID_AINR_YUV);

                 if (feature & MTK_FEATURE_AINR_YHDR)

4.2 将算法对应的feature添加到scenario配置表

在我们打开camera进行预览和拍照的时候,MTK HAL3会执行vendor/mediatek/proprietary/hardware/mtkcam3/pipeline/policy/FeatureSettingPolicy.cpp的代码,会分别调用

vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/scenario_mgr.cpp的

get_streaming_scenario函数和get_capture_scenario函数。它们会读取一个scenario的feature配置表,遍历所有的feature,决定哪些feature会被执行。这个配置表中有许多的scenario,一个scenario可能对应多个feature。因此添加自定义feature后,还需将自定义的feature添加到配置表中。MTK feature 对应的配置表是 gMtkScenarioFeaturesMaps,customer feature 对应的配置表是 gCustomerScenarioFeaturesMaps。

vendor/mediatek/proprietary/custom/mt6765/hal/camera/camera_custom_feature_table.cpp

#include "camera_custom_feature_table.h"

using namespace NSCam::NSPipelinePlugin;

// ======================================================================================================

// For Camera HAL Server

// ======================================================================================================

// TODO: Feature Combinations for MTK Camera HAL server

// #define  <feature combination>              (key feature         | post-processing features | ...)

//

// logical stream

// single cam capture feature combination

#define MTK_FEATURE_COMBINATION_SINGLE         (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB| TP_FEATURE_WATERMARK)

#define MTK_FEATURE_COMBINATION_HDR            (TP_FEATURE_HDR      | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB| TP_FEATURE_WATERMARK)

#define MTK_FEATURE_COMBINATION_AINR           (MTK_FEATURE_AINR    | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB| TP_FEATURE_WATERMARK)

#define MTK_FEATURE_COMBINATION_AIHDR          (MTK_FEATURE_AIHDR   | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB)

#define MTK_FEATURE_COMBINATION_REMOSAIC_MFNR  (MTK_FEATURE_REMOSAIC_MFNR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB)

#define MTK_FEATURE_COMBINATION_MFNR           (MTK_FEATURE_MFNR    | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB| TP_FEATURE_WATERMARK)

#define MTK_FEATURE_COMBINATION_REMOSAIC       (MTK_FEATURE_REMOSAIC| MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB| TP_FEATURE_WATERMARK)

#define MTK_FEATURE_COMBINATION_CSHOT          (NO_FEATURE_NORMAL   | MTK_FEATURE_CZ| MTK_FEATURE_HFG)

#define MTK_FEATURE_COMBINATION_MULTICAM       (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB)

#define MTK_FEATURE_COMBINATION_YUV_REPROCESS  (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_FB| TP_FEATURE_WATERMARK)

#define MTK_FEATURE_COMBINATION_RAW_REPROCESS  (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE| TP_FEATURE_FB| TP_FEATURE_WATERMARK)

#define MTK_FEATURE_COMBINATION_SUPER_NIGHT_RAW_REPROCESS (NO_FEATURE_NORMAL | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE| TP_FEATURE_FB| TP_FEATURE_WATERMARK)

// request source frame from camerahalserver.

// no feature pure image quality for processing, the full image processing will be process in isp hidl.

#define MTK_FEATURE_COMBINATION_ISP_HIDL_SOURCE_COMMON  (NO_FEATURE_NORMAL | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE)

#define MTK_FEATURE_COMBINATION_ISP_HIDL_SOURCE_MFNR    (MTK_FEATURE_MFNR  | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE)

#define MTK_FEATURE_COMBINATION_ISP_HIDL_SOURCE_AINR    (MTK_FEATURE_AINR  | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE)

// dual cam capture feature combination

// the VSDOF means the combination of Bokeh feature and Depth feature

#define MTK_FEATURE_COMBINATION_MTK_VSDOF          (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB| MTK_FEATURE_VSDOF| TP_FEATURE_WATERMARK)

#define MTK_FEATURE_COMBINATION_MTK_VSDOF_HDR      (TP_FEATURE_HDR_DC   | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB| MTK_FEATURE_VSDOF| TP_FEATURE_WATERMARK)

#define MTK_FEATURE_COMBINATION_MTK_VSDOF_MFNR     (MTK_FEATURE_MFNR    | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB| MTK_FEATURE_VSDOF| TP_FEATURE_WATERMARK)

#define MTK_FEATURE_COMBINATION_MTK_VSDOF_AINR     (MTK_FEATURE_AINR    | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB| MTK_FEATURE_AINR_YUV| MTK_FEATURE_VSDOF)

// zoom fusion combination, need TP_FEATURE_ZOOM_FUSION when sensor nums >= 2 && has tp fusion plugin

#define MTK_FEATURE_COMBINATION_MTK_ZOOM          (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB| TP_FEATURE_ZOOM_FUSION)

#define MTK_FEATURE_COMBINATION_MTK_ZOOM_HDR      (TP_FEATURE_HDR      | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB| TP_FEATURE_ZOOM_FUSION)

#define MTK_FEATURE_COMBINATION_MTK_ZOOM_AINR     (MTK_FEATURE_AINR    | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB| TP_FEATURE_ZOOM_FUSION)

#define MTK_FEATURE_COMBINATION_MTK_ZOOM_AIHDR    (MTK_FEATURE_AIHDR   | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB| TP_FEATURE_ZOOM_FUSION)

#define MTK_FEATURE_COMBINATION_MTK_ZOOM_MFNR     (MTK_FEATURE_MFNR    | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB| TP_FEATURE_ZOOM_FUSION)

#define MTK_FEATURE_COMBINATION_MTK_ZOOM_REMOSAIC (MTK_FEATURE_REMOSAIC| MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB| TP_FEATURE_ZOOM_FUSION)

// physical stream

// single cam capture feature combination

#define MTK_FEATURE_COMBINATION_MASTER          (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB)

#define MTK_FEATURE_COMBINATION_SLAVE           (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB)

#define MTK_FEATURE_COMBINATION_REMOSAIC_MASTER (MTK_FEATURE_REMOSAIC| MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB)

#define MTK_FEATURE_COMBINATION_REMOSAIC_SLAVE  (MTK_FEATURE_REMOSAIC| MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB)

#define MTK_FEATURE_COMBINATION_MULTICAM_MASTER (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB)

#define MTK_FEATURE_COMBINATION_MULTICAM_SLAVE  (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB)

//

#define MTK_FEATURE_COMBINATION_VSDOF_MASTER    (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB)

#define MTK_FEATURE_COMBINATION_VSDOF_SLAVE     (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB)

#define MTK_FEATURE_COMBINATION_ZOOM_MASTER   (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB)

#define MTK_FEATURE_COMBINATION_ZOOM_SLAVE    (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB)

#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)

// request source frame from camerahalserver.

// no feature pure image quality for processing, the full image processing will be process in isp hidl.

#define MTK_FEATURE_COMBINATION_YUV_REPROCESS_MASTER        (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_FB)

#define MTK_FEATURE_COMBINATION_RAW_REPROCESS_MASTER        (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE| TP_FEATURE_FB)

#define MTK_FEATURE_COMBINATION_YUV_REPROCESS_SLAVE         (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_FB)

#define MTK_FEATURE_COMBINATION_RAW_REPROCESS_SLAVE         (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE| TP_FEATURE_FB)

// streaming feature combination (TODO: it should be refined by streaming scenario feature)

#define MTK_FEATURE_COMBINATION_VIDEO_NORMAL     (MTK_FEATURE_FB|MTK_FEATURE_ASYNC_ASD|MTK_FEATURE_EIS|TP_FEATURE_FB|TP_FEATURE_ASYNC_ASD|TP_FEATURE_EIS|MTK_FEATURE_FOVA|TP_FEATURE_WATERMARK)

#define MTK_FEATURE_COMBINATION_VIDEO_NORMAL_VIDEO   (MTK_FEATURE_FB|MTK_FEATURE_ASYNC_ASD|MTK_FEATURE_EIS|TP_FEATURE_FB|TP_FEATURE_ASYNC_ASD|TP_FEATURE_EIS|MTK_FEATURE_FOVA)

#define MTK_FEATURE_COMBINATION_VIDEO_DUAL_YUV   (MTK_FEATURE_FB|MTK_FEATURE_ASYNC_ASD|MTK_FEATURE_EIS|MTK_FEATURE_DUAL_YUV|TP_FEATURE_FB|TP_FEATURE_ASYNC_ASD|TP_FEATURE_EIS|TP_FEATURE_DUAL_YUV|TP_FEATURE_WATERMARK)

#define MTK_FEATURE_COMBINATION_VIDEO_DUAL_HWDEPTH (MTK_FEATURE_FB|MTK_FEATURE_ASYNC_ASD|MTK_FEATURE_EIS|MTK_FEATURE_DUAL_HWDEPTH|TP_FEATURE_FB|TP_FEATURE_ASYNC_ASD|TP_FEATURE_EIS|TP_FEATURE_DUAL_HWDEPTH|TP_FEATURE_WATERMARK)

#define MTK_FEATURE_COMBINATION_VIDEO_DUAL_HWVSDOF (MTK_FEATURE_FB|TP_FEATURE_FB|TP_FEATURE_WATERMARK)

// ======================================================================================================

//

// add scenario/feature set for logical camera scenario

const std::vector<std::unordered_map<int32_t, ScenarioFeatures>>  gCustomerScenarioFeaturesMaps =

{

    {

        // capture

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_CAPTURE_NORMAL)

        ADD_CAMERA_FEATURE_SET(MTK_FEATURE_AIHDR,    MTK_FEATURE_COMBINATION_AIHDR)

        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_REMOSAIC_MFNR, MTK_FEATURE_COMBINATION_REMOSAIC_MFNR)

        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

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_CAPTURE_VSDOF)

        ADD_CAMERA_FEATURE_SET(TP_FEATURE_HDR_DC, MTK_FEATURE_COMBINATION_MTK_VSDOF_HDR)

        ADD_CAMERA_FEATURE_SET(MTK_FEATURE_MFNR,  MTK_FEATURE_COMBINATION_MTK_VSDOF_MFNR)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_MTK_VSDOF)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_CAPTURE_MULTICAM)

        ADD_CAMERA_FEATURE_SET(MTK_FEATURE_AIHDR,    MTK_FEATURE_COMBINATION_AIHDR)

        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(MTK_FEATURE_REMOSAIC, MTK_FEATURE_COMBINATION_REMOSAIC)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL,    MTK_FEATURE_COMBINATION_MULTICAM)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_CAPTURE_ZOOM)

        ADD_CAMERA_FEATURE_SET(TP_FEATURE_HDR,       MTK_FEATURE_COMBINATION_MTK_ZOOM_HDR)

        ADD_CAMERA_FEATURE_SET(MTK_FEATURE_AINR,     MTK_FEATURE_COMBINATION_MTK_ZOOM_AINR)

        ADD_CAMERA_FEATURE_SET(MTK_FEATURE_MFNR,     MTK_FEATURE_COMBINATION_MTK_ZOOM_MFNR)

        ADD_CAMERA_FEATURE_SET(MTK_FEATURE_REMOSAIC, MTK_FEATURE_COMBINATION_MTK_ZOOM_REMOSAIC)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL,    MTK_FEATURE_COMBINATION_MTK_ZOOM)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_CAPTURE_CSHOT)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_CSHOT)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_CAPTURE_DNG_OPAQUE_RAW)

        /* not support multiframe features with dng capture yet */

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_SINGLE)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_CAPTURE_YUV_REPROCESS)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_YUV_REPROCESS)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_CAPTURE_RAW_REPROCESS)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_RAW_REPROCESS)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(CUSTOMER_CAMERA_SCENARIO_CAPTURE_SUPER_NIGHT)

        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(NO_FEATURE_NORMAL,    MTK_FEATURE_COMBINATION_SINGLE)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(CUSTOMER_CAMERA_SCENARIO_CAPTURE_SUPER_NIGHT_RAW_REPROCESS)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_SUPER_NIGHT_RAW_REPROCESS)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_CAPTURE_REQUEST_FRAME_FOR_ISP_HIDL_YUV)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_ISP_HIDL_SOURCE_COMMON)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_CAPTURE_REQUEST_FRAME_FOR_ISP_HIDL_RAW)

        ADD_CAMERA_FEATURE_SET(MTK_FEATURE_AINR,  MTK_FEATURE_COMBINATION_ISP_HIDL_SOURCE_AINR)

        ADD_CAMERA_FEATURE_SET(MTK_FEATURE_MFNR,  MTK_FEATURE_COMBINATION_ISP_HIDL_SOURCE_MFNR)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_ISP_HIDL_SOURCE_COMMON)

        CAMERA_SCENARIO_END

        //

        // streaming

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_STREAMING_NORMAL)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_VIDEO_NORMAL)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_STREAMING_NORMAL_VIDEO)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_VIDEO_NORMAL_VIDEO)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_STREAMING_DUAL_YUV)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_VIDEO_DUAL_YUV)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_STREAMING_DUAL_HWDEPTH)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_VIDEO_DUAL_HWDEPTH)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_STREAMING_DUAL_HWVSDOF)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_VIDEO_DUAL_HWVSDOF)

        CAMERA_SCENARIO_END

    },

};

// add scenario/feature set for master physical camera scenario

const std::vector<std::unordered_map<int32_t, ScenarioFeatures>>  gCustomerScenarioFeaturesMapsPhyMaster =

{

    {

        // capture physical master

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_CAPTURE_NORMAL)

        ADD_CAMERA_FEATURE_SET(MTK_FEATURE_REMOSAIC, MTK_FEATURE_COMBINATION_REMOSAIC_MASTER)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL,    MTK_FEATURE_COMBINATION_MASTER)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_CAPTURE_VSDOF)

        ADD_CAMERA_FEATURE_SET(MTK_FEATURE_REMOSAIC, MTK_FEATURE_COMBINATION_REMOSAIC_MASTER)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_VSDOF_MASTER)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_CAPTURE_MULTICAM)

        ADD_CAMERA_FEATURE_SET(MTK_FEATURE_REMOSAIC, MTK_FEATURE_COMBINATION_REMOSAIC_MASTER)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_MULTICAM_MASTER)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_CAPTURE_ZOOM)

        ADD_CAMERA_FEATURE_SET(MTK_FEATURE_REMOSAIC, MTK_FEATURE_COMBINATION_REMOSAIC_MASTER)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_ZOOM_MASTER)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_CAPTURE_YUV_REPROCESS)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_YUV_REPROCESS_MASTER)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_CAPTURE_RAW_REPROCESS)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_RAW_REPROCESS_MASTER)

        CAMERA_SCENARIO_END

        //

        // streaming

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_STREAMING_NORMAL)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_VIDEO_NORMAL)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_STREAMING_NORMAL_VIDEO)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_VIDEO_NORMAL_VIDEO)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_STREAMING_DUAL_YUV)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_VIDEO_DUAL_YUV)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_STREAMING_DUAL_HWDEPTH)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_VIDEO_DUAL_HWDEPTH)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_STREAMING_DUAL_HWVSDOF)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_VIDEO_DUAL_HWVSDOF)

        CAMERA_SCENARIO_END

    },

};

// add scenario/feature set for slave physical camera scenario

const std::vector<std::unordered_map<int32_t, ScenarioFeatures>>  gCustomerScenarioFeaturesMapsPhySlave =

{

    {

        // capture physical slave

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_CAPTURE_NORMAL)

        ADD_CAMERA_FEATURE_SET(MTK_FEATURE_REMOSAIC, MTK_FEATURE_COMBINATION_REMOSAIC_SLAVE)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL,    MTK_FEATURE_COMBINATION_SLAVE)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_CAPTURE_VSDOF)

        ADD_CAMERA_FEATURE_SET(MTK_FEATURE_REMOSAIC, MTK_FEATURE_COMBINATION_REMOSAIC_SLAVE)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_VSDOF_SLAVE)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_CAPTURE_MULTICAM)

        ADD_CAMERA_FEATURE_SET(MTK_FEATURE_REMOSAIC, MTK_FEATURE_COMBINATION_REMOSAIC_SLAVE)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_MULTICAM_SLAVE)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_CAPTURE_ZOOM)

        ADD_CAMERA_FEATURE_SET(MTK_FEATURE_REMOSAIC, MTK_FEATURE_COMBINATION_REMOSAIC_SLAVE)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_ZOOM_SLAVE)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_CAPTURE_YUV_REPROCESS)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_YUV_REPROCESS_SLAVE)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_CAPTURE_RAW_REPROCESS)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_RAW_REPROCESS_SLAVE)

        CAMERA_SCENARIO_END

        //

        // streaming

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_STREAMING_NORMAL)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_VIDEO_NORMAL)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_STREAMING_NORMAL_VIDEO)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_VIDEO_NORMAL_VIDEO)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_STREAMING_DUAL_YUV)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_VIDEO_DUAL_YUV)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_STREAMING_DUAL_HWDEPTH)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_VIDEO_DUAL_HWDEPTH)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_CAMERA_SCENARIO_STREAMING_DUAL_HWVSDOF)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL, MTK_FEATURE_COMBINATION_VIDEO_DUAL_HWVSDOF)

        CAMERA_SCENARIO_END

    },

};

// ======================================================================================================

// For ISP HIDL only

// ======================================================================================================

// TODO: Feature Combinations for MTK ISP Device HIDL

// #define  <feature combination>              (key feature         | post-processing features | ...)

//

// isp hidl feature combination

#define MTK_FEATURE_COMBINATION_SINGLE_FULL         (NO_FEATURE_NORMAL | MTK_FEATURE_DCE| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_NR| MTK_FEATURE_CZ)

#define MTK_FEATURE_COMBINATION_AINR_FULL           (MTK_FEATURE_AINR  | MTK_FEATURE_DCE| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_NR| MTK_FEATURE_CZ)

#define MTK_FEATURE_COMBINATION_MFNR_FULL           (MTK_FEATURE_MFNR  | MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_NR| MTK_FEATURE_CZ)

// single frame in

#define MTK_FEATURE_COMBINATION_SINGLE_RAW_TO_YUV   (NO_FEATURE_NORMAL | MTK_FEATURE_DCE| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_NR| MTK_FEATURE_CZ)

#define MTK_FEATURE_COMBINATION_SINGLE_RAW_TO_JPEG  (NO_FEATURE_NORMAL | MTK_FEATURE_DCE| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_NR| MTK_FEATURE_CZ)

#define MTK_FEATURE_COMBINATION_SINGLE_YUV_TO_YUV   (NO_FEATURE_NORMAL) // image transform and crop/resize only

#define MTK_FEATURE_COMBINATION_SINGLE_YUV_TO_JPEG  (NO_FEATURE_NORMAL) // encode yuv to jpeg only.

// multiple frame in

#define MTK_FEATURE_COMBINATION_AINR_RAW_TO_RAW     (MTK_FEATURE_AINR)  // output AINR RAW only

#define MTK_FEATURE_COMBINATION_AINR_RAW_TO_YUV     (MTK_FEATURE_AINR  | MTK_FEATURE_DCE| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_NR| MTK_FEATURE_CZ)

#define MTK_FEATURE_COMBINATION_AINR_RAW_TO_JPEG    (MTK_FEATURE_AINR  | MTK_FEATURE_DCE| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_NR| MTK_FEATURE_CZ)

#define MTK_FEATURE_COMBINATION_MFNR_RAW_TO_YUV     (MTK_FEATURE_MFNR  | MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_NR| MTK_FEATURE_CZ)

#define MTK_FEATURE_COMBINATION_MFNR_RAW_TO_JPEG    (MTK_FEATURE_MFNR  | MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_NR| MTK_FEATURE_CZ)

// ======================================================================================================

//

const std::vector<std::unordered_map<int32_t, ScenarioFeatures>>  gCustomerIspHidlScenarioFeaturesMaps =

{

    {

        // capture

        CAMERA_SCENARIO_START(MTK_ISP_HIDL_SCENARIO_CAPTURE_ALL)

        ADD_CAMERA_FEATURE_SET(MTK_FEATURE_AINR,     MTK_FEATURE_COMBINATION_AINR_FULL)

        ADD_CAMERA_FEATURE_SET(MTK_FEATURE_MFNR,     MTK_FEATURE_COMBINATION_MFNR_FULL)

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL,    MTK_FEATURE_COMBINATION_SINGLE_FULL)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_ISP_HIDL_SCENARIO_CAPTURE_SINGLE_RAW_TO_YUV) // encode single raw to yuv

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL,    MTK_FEATURE_COMBINATION_SINGLE_RAW_TO_YUV)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_ISP_HIDL_SCENARIO_CAPTURE_SINGLE_RAW_TO_JPEG) // encode single raw to yuv and encode to jepg

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL,    MTK_FEATURE_COMBINATION_SINGLE_RAW_TO_JPEG)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_ISP_HIDL_SCENARIO_CAPTURE_SINGLE_YUV_TO_YUV) // single yuv reprocessing

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL,    MTK_FEATURE_COMBINATION_SINGLE_YUV_TO_YUV)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_ISP_HIDL_SCENARIO_CAPTURE_SINGLE_YUV_TO_JPEG) // encode single yuv to jpeg

        ADD_CAMERA_FEATURE_SET(NO_FEATURE_NORMAL,    MTK_FEATURE_COMBINATION_SINGLE_YUV_TO_JPEG)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_ISP_HIDL_SCENARIO_CAPTURE_MULTIPLE_RAW_TO_RAW) // multiframe raw to single raw

        ADD_CAMERA_FEATURE_SET(MTK_FEATURE_AINR,     MTK_FEATURE_COMBINATION_AINR_RAW_TO_RAW)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_ISP_HIDL_SCENARIO_CAPTURE_MULTIPLE_RAW_TO_YUV) // multiframe raw to single yuv

        ADD_CAMERA_FEATURE_SET(MTK_FEATURE_AINR,     MTK_FEATURE_COMBINATION_AINR_RAW_TO_YUV)

        ADD_CAMERA_FEATURE_SET(MTK_FEATURE_MFNR,     MTK_FEATURE_COMBINATION_MFNR_RAW_TO_YUV)

        CAMERA_SCENARIO_END

        //

        CAMERA_SCENARIO_START(MTK_ISP_HIDL_SCENARIO_CAPTURE_MULTIPLE_RAW_TO_JPEG) // multiframe raw to jpeg

        ADD_CAMERA_FEATURE_SET(MTK_FEATURE_AINR,     MTK_FEATURE_COMBINATION_AINR_RAW_TO_JPEG)

        ADD_CAMERA_FEATURE_SET(MTK_FEATURE_MFNR,     MTK_FEATURE_COMBINATION_MFNR_RAW_TO_JPEG)

        CAMERA_SCENARIO_END

    },

};

vendor/mediatek/proprietary/packages/apps/Camera2/camerapostalgo/main/3rdparty/mtk/mtk_scenario_mgr.cpp

@@ -80,31 +80,31 @@ using namespace NSCam::v3::pipeline::policy::scenariomgr;

 // #define  <feature combination>              (key feature         | post-processing features | ...)

 //

 // single cam capture feature combination

-#define MTK_FEATURE_COMBINATION_SINGLE         (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_ABF| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB)

-#define MTK_FEATURE_COMBINATION_HDR            (TP_FEATURE_HDR      | MTK_FEATURE_NR| MTK_FEATURE_ABF| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB)

-#define MTK_FEATURE_COMBINATION_AINR           (MTK_FEATURE_AINR    | MTK_FEATURE_NR| MTK_FEATURE_ABF| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB)

+#define MTK_FEATURE_COMBINATION_SINGLE         (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_WATERMARK)

+#define MTK_FEATURE_COMBINATION_HDR            (TP_FEATURE_HDR      | MTK_FEATURE_NR| MTK_FEATURE_ABF| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB| TP_FEATURE_WATERMARK)

+#define MTK_FEATURE_COMBINATION_AINR           (MTK_FEATURE_AINR    | MTK_FEATURE_NR| MTK_FEATURE_ABF| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB| T

P_FEATURE_WATERMARK)

 #define MTK_FEATURE_COMBINATION_AINR_HDR       (MTK_FEATURE_AINR_YHDR| MTK_FEATURE_NR| MTK_FEATURE_ABF| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB)

-#define MTK_FEATURE_COMBINATION_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)

-#define MTK_FEATURE_COMBINATION_REMOSAIC       (MTK_FEATURE_REMOSAIC| MTK_FEATURE_NR| MTK_FEATURE_ABF| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB)

+#define MTK_FEATURE_COMBINATION_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| T

P_FEATURE_WATERMARK)

+#define MTK_FEATURE_COMBINATION_REMOSAIC       (MTK_FEATURE_REMOSAIC| MTK_FEATURE_NR| MTK_FEATURE_ABF| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_FB| T

P_FEATURE_WATERMARK)

 #define MTK_FEATURE_COMBINATION_CSHOT          (NO_FEATURE_NORMAL   | MTK_FEATURE_CZ| MTK_FEATURE_HFG)

 #define MTK_FEATURE_COMBINATION_MULTICAM       (NO_FEATURE_NORMAL)

-#define MTK_FEATURE_COMBINATION_YUV_REPROCESS  (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_FB)

-#define MTK_FEATURE_COMBINATION_RAW_REPROCESS  (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE| TP_FEATURE_FB)

-#define MTK_FEATURE_COMBINATION_SUPER_NIGHT_RAW_REPROCESS (NO_FEATURE_NORMAL | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE| TP_FEATURE_FB)

+#define MTK_FEATURE_COMBINATION_YUV_REPROCESS  (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_FB| TP_FEATURE_WATERMARK)

+#define MTK_FEATURE_COMBINATION_RAW_REPROCESS  (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE| TP_FEATURE_FB| TP_FEATURE_WATERMARK

)

+#define MTK_FEATURE_COMBINATION_SUPER_NIGHT_RAW_REPROCESS (NO_FEATURE_NORMAL | MTK_FEATURE_NR| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE| TP_FEATURE_FB| TP_FEATURE_

WATERMARK)

 // dual cam capture feature combination

 // the VSDOF means the combination of Bokeh feature and Depth feature

-#define MTK_FEATURE_COMBINATION_MTK_VSDOF          (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_ABF| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_F

B| MTK_FEATURE_VSDOF)

-#define MTK_FEATURE_COMBINATION_MTK_VSDOF_HDR      (TP_FEATURE_HDR_DC   | MTK_FEATURE_NR| MTK_FEATURE_ABF| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_F

B| MTK_FEATURE_VSDOF)

-#define MTK_FEATURE_COMBINATION_MTK_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_F

B| MTK_FEATURE_VSDOF)

+#define MTK_FEATURE_COMBINATION_MTK_VSDOF          (NO_FEATURE_NORMAL   | MTK_FEATURE_NR| MTK_FEATURE_ABF| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_F

B| MTK_FEATURE_VSDOF| TP_FEATURE_WATERMARK)

+#define MTK_FEATURE_COMBINATION_MTK_VSDOF_HDR      (TP_FEATURE_HDR_DC   | MTK_FEATURE_NR| MTK_FEATURE_ABF| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_F

B| MTK_FEATURE_VSDOF| TP_FEATURE_WATERMARK)

+#define MTK_FEATURE_COMBINATION_MTK_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_F

B| MTK_FEATURE_VSDOF| TP_FEATURE_WATERMARK)

 #define MTK_FEATURE_COMBINATION_MTK_VSDOF_AINR     (MTK_FEATURE_AINR    | MTK_FEATURE_NR| MTK_FEATURE_ABF| MTK_FEATURE_CZ| MTK_FEATURE_DRE| MTK_FEATURE_HFG| MTK_FEATURE_DCE | MTK_FEATURE_F

B| MTK_FEATURE_AINR_YUV| MTK_FEATURE_VSDOF)

 // streaming feature combination (TODO: it should be refined by streaming scenario feature)

-#define MTK_FEATURE_COMBINATION_VIDEO_NORMAL     (MTK_FEATURE_FB|MTK_FEATURE_ASYNC_ASD|MTK_FEATURE_EIS|TP_FEATURE_FB|TP_FEATURE_ASYNC_ASD|TP_FEATURE_EIS|MTK_FEATURE_FOVA)

+#define MTK_FEATURE_COMBINATION_VIDEO_NORMAL     (MTK_FEATURE_FB|MTK_FEATURE_ASYNC_ASD|MTK_FEATURE_EIS|TP_FEATURE_FB|TP_FEATURE_ASYNC_ASD|TP_FEATURE_EIS|MTK_FEATURE_FOVA|TP_FEATURE_WATERMA

RK)

 #define MTK_FEATURE_COMBINATION_VIDEO_NORMAL_VIDEO   (MTK_FEATURE_FB|MTK_FEATURE_ASYNC_ASD|MTK_FEATURE_EIS|TP_FEATURE_FB|TP_FEATURE_ASYNC_ASD|TP_FEATURE_EIS|MTK_FEATURE_FOVA)

-#define MTK_FEATURE_COMBINATION_VIDEO_DUAL_YUV   (MTK_FEATURE_FB|MTK_FEATURE_ASYNC_ASD|MTK_FEATURE_EIS|MTK_FEATURE_DUAL_YUV|TP_FEATURE_FB|TP_FEATURE_ASYNC_ASD|TP_FEATURE_EIS|TP_FEATURE_DUA

L_YUV)

-#define MTK_FEATURE_COMBINATION_VIDEO_DUAL_HWDEPTH (MTK_FEATURE_FB|MTK_FEATURE_ASYNC_ASD|MTK_FEATURE_EIS|MTK_FEATURE_DUAL_HWDEPTH|TP_FEATURE_FB|TP_FEATURE_ASYNC_ASD|TP_FEATURE_EIS|TP_FEATU

RE_DUAL_HWDEPTH)

-#define MTK_FEATURE_COMBINATION_VIDEO_DUAL_HWVSDOF (MTK_FEATURE_FB|TP_FEATURE_FB)

+#define MTK_FEATURE_COMBINATION_VIDEO_DUAL_YUV   (MTK_FEATURE_FB|MTK_FEATURE_ASYNC_ASD|MTK_FEATURE_EIS|MTK_FEATURE_DUAL_YUV|TP_FEATURE_FB|TP_FEATURE_ASYNC_ASD|TP_FEATURE_EIS|TP_FEATURE_DUA

L_YUV|TP_FEATURE_WATERMARK)

+#define MTK_FEATURE_COMBINATION_VIDEO_DUAL_HWDEPTH (MTK_FEATURE_FB|MTK_FEATURE_ASYNC_ASD|MTK_FEATURE_EIS|MTK_FEATURE_DUAL_HWDEPTH|TP_FEATURE_FB|TP_FEATURE_ASYNC_ASD|TP_FEATURE_EIS|TP_FEATU

RE_DUAL_HWDEPTH|TP_FEATURE_WATERMARK)

+#define MTK_FEATURE_COMBINATION_VIDEO_DUAL_HWVSDOF (MTK_FEATURE_FB|TP_FEATURE_FB|TP_FEATURE_WATERMARK)

4.3 为算法选择plugin

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。

单帧水印算法,所以预览我们选择JoinPlugin,拍照选择YuvPlugin。

多帧算法,只能选择MultiFramePlugin。并且,一般情况下多帧算法只用于拍照,不用于预览。

4.4 编写算法集成文件

水印算法目录结构

参照 FBImpl.cpp 和 sample_streaming_fb.cpp 中分别实现拍照和预览。目录结构如下:

vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/customer/tp_watermark/

├── Android.mk

├── include

│ └── watermark.h

├── lib

│ ├── arm64-v8a

│ │ └── libwatermark.so

│ └── armeabi-v7a

│ └── libwatermark.so

├── res

│ └── watermark.rgba

├── WatermarkCapture.cpp

└── WatermarkPreview.cpp

文件说明:

Android.mk中配置算法库、头文件、集成的源代码CPP文件编译成库libmtkcam.plugin.tp_watermark,供libmtkcam_3rdparty.customer依赖调用。

集成的源代码CPP文件,WatermarkCapture.cpp用于拍照,WatermarkPreview.cpp用于预览。

libwatermark.so实现了添加水印的功能,libwatermark.so用来模拟需要接入的第三方算法库。watermark.h是头文件。

watermark.rgba是对应的水印文件。

多帧算法目录结构

参照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文件。

4.5 开撸代码

添加全局宏控,是否编译三方算法

device/mediateksample/[platform]/ProjectConfig.mk


@@ -5,6 +5,8 @@ AUTO_ADD_GLOBAL_DEFINE_BY_VALUE = BOOT_LOGO MTK_PLATFORM CUSTOM_KERNEL_MAIN_IMGS

 BUILD_KERNEL = yes

+QXT_MFNR_SUPPORT = yes

+QXT_WATERMARK_SUPPORT = yes

 BUILD_LK = yes

新增 vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/customer/tp_watermark/ 文件夹

vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/customer/tp_watermark/Android.mk

ifeq ($(QXT_WATERMARK_SUPPORT),yes)

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := libwatermark

LOCAL_SRC_FILES_32 := lib/armeabi-v7a/libwatermark.so

LOCAL_SRC_FILES_64 := lib/arm64-v8a/libwatermark.so

LOCAL_MODULE_TAGS := optional

LOCAL_MODULE_CLASS := SHARED_LIBRARIES

LOCAL_MODULE_SUFFIX := .so

LOCAL_PROPRIETARY_MODULE := true

LOCAL_CHECK_ELF_FILES := false

LOCAL_MULTILIB := both

include $(BUILD_PREBUILT)

################################################################################

################################################################################

include $(CLEAR_VARS)

#-----------------------------------------------------------

include $(TOP)/$(MTK_PATH_SOURCE)/hardware/mtkcam/mtkcam.mk

#-----------------------------------------------------------

LOCAL_SRC_FILES += WatermarkCapture.cpp

LOCAL_SRC_FILES += WatermarkPreview.cpp

#-----------------------------------------------------------

LOCAL_C_INCLUDES += $(MTKCAM_C_INCLUDES)

LOCAL_C_INCLUDES += $(TOP)/$(MTK_PATH_SOURCE)/hardware/mtkcam3/include

LOCAL_C_INCLUDES += $(TOP)/$(MTK_PATH_SOURCE)/hardware/mtkcam/include

#

LOCAL_C_INCLUDES += system/media/camera/include

LOCAL_C_INCLUDES += $(TOP)/external/libyuv/files/include/

LOCAL_C_INCLUDES += $(TOP)/$(MTK_PATH_SOURCE)/hardware/mtkcam3/3rdparty/customer/tp_watermark/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 += libyuv.vendor

#-----------------------------------------------------------

LOCAL_HEADER_LIBRARIES := libutils_headers liblog_headers libhardware_headers

#-----------------------------------------------------------

LOCAL_MODULE := libmtkcam.plugin.tp_watermark

LOCAL_PROPRIETARY_MODULE := true

LOCAL_MODULE_OWNER := mtk

LOCAL_MODULE_TAGS := optional

include $(MTK_STATIC_LIBRARY)

################################################################################

include $(call all-makefiles-under,$(LOCAL_PATH))

endif

新增

vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/customer/tp_watermark/include/watermark.h

#include <stdio.h>

#include <string.h>

// #include <android/log.h>

namespace Watermark

{

    void add(unsigned char* src, int srcWidth, int srcHeight, unsigned char* watermark,

              int watermarkWidth, int watermarkHeight, int x, int y);




新增

vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/customer/tp_watermark/WatermarkCapture.cpp

主要函数介绍:

在property函数中feature类型设置我们在第三步中添加的TP_FEATURE_WATERMARK,并设置名称、优先级等等属性。

在negotiate函数中配置算法需要的输入、输出图像的格式、尺寸。

在negotiate函数或者process函数中获取上层传下来的metadata参数,根据参数决定算法是否运行,或者将参数传给算法。

在process函数中接入算法。

#define LOG_TAG "WatermarkCapture"

//

#include <mtkcam/utils/std/Log.h>

//

#include <stdlib.h>

#include <utils/Errors.h>

#include <utils/List.h>

#include <utils/RefBase.h>

#include <sstream>

//

#include <mtkcam/utils/metadata/client/mtk_metadata_tag.h>

#include <mtkcam/utils/metadata/hal/mtk_platform_metadata_tag.h>

//

//

#include <mtkcam/utils/imgbuf/IIonImageBufferHeap.h>

//

#include <mtkcam/drv/IHalSensor.h>

#include <mtkcam/utils/std/Format.h>

//

#include <mtkcam3/pipeline/hwnode/NodeId.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 <stdlib.h>

#include <watermark.h>

#include <mtkcam/utils/std/Time.h>

#include <time.h>

#include <libyuv.h>

//

using namespace NSCam;

using namespace android;

using namespace std;

using namespace NSCam::NSPipelinePlugin;

/******************************************************************************

 *

 ******************************************************************************/

#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 FUNCTION_IN                 MY_LOGD("%s +", __FUNCTION__)

#define FUNCTION_OUT                MY_LOGD("%s -", __FUNCTION__)

//systrace

#if 1

#ifndef ATRACE_TAG

#define ATRACE_TAG                           ATRACE_TAG_CAMERA

#endif

#include <utils/Trace.h>

#define WATERMARK_TRACE_CALL()                      ATRACE_CALL()

#define WATERMARK_TRACE_NAME(name)                  ATRACE_NAME(name)

#define WATERMARK_TRACE_BEGIN(name)                 ATRACE_BEGIN(name)

#define WATERMARK_TRACE_END()                       ATRACE_END()

#else

#define WATERMARK_TRACE_CALL()

#define WATERMARK_TRACE_NAME(name)

#define WATERMARK_TRACE_BEGIN(name)

#define WATERMARK_TRACE_END()

#endif

template <class T>

inline bool

tryGetMetadata(IMetadata const *pMetadata, MUINT32 tag, T& rVal)

{

    if(pMetadata == nullptr) return MFALSE;

    IMetadata::IEntry entry = pMetadata->entryFor(tag);

    if(!entry.isEmpty())

    {

        rVal = entry.itemAt(0,Type2Type<T>());

        return true;

    }

    else

    {

#define var(v) #v

#define type(t) #t

        MY_LOGW("no metadata %s in %s", var(tag), type(pMetadata));

#undef type

#undef var

    }

    return false;

}

/******************************************************************************

*

******************************************************************************/

class WatermarkCapture : public YuvPlugin::IProvider {

public:

    typedef YuvPlugin::Property Property;

    typedef YuvPlugin::Selection Selection;

    typedef YuvPlugin::Request::Ptr RequestPtr;

    typedef YuvPlugin::RequestCallback::Ptr RequestCallbackPtr;

private:

    int mOpenid;

    MBOOL mEnable = 1;

    MBOOL mDump = 0;

    unsigned char *mSrcRGBA = nullptr;

    unsigned char *mWatermarkRGBA = nullptr;

    int mWatermarkWidth = 0;

    int mWatermarkHeight = 0;

public:

    WatermarkCapture();

    ~WatermarkCapture();

    void init();

    void uninit();

    void abort(vector <RequestPtr> &pRequests);

    void set(MINT32 iOpenId, MINT32 iOpenId2);

    const Property &property();

    MERROR negotiate(Selection &sel);

    MERROR process(RequestPtr pRequest, RequestCallbackPtr pCallback);

};

WatermarkCapture::WatermarkCapture() : mOpenid(-1) {

    FUNCTION_IN;

    mEnable = property_get_bool("vendor.debug.camera.watermark.capture.enable", 1);

    mDump = property_get_bool("vendor.debug.camera.watermark.capture.dump", 0);

    FUNCTION_OUT;

}

WatermarkCapture::~WatermarkCapture() {

    FUNCTION_IN;

    FUNCTION_OUT;

}

void WatermarkCapture::init() {

    FUNCTION_IN;

    mWatermarkWidth = 180;

    mWatermarkHeight = 640;

    int watermarkSize = mWatermarkWidth * mWatermarkHeight * 4;

    mWatermarkRGBA = (unsigned char *) malloc(watermarkSize);

    FILE *fp;

    char path[256];

    snprintf(path, sizeof(path), "/vendor/res/images/watermark.rgba");

    if ((fp = fopen(path, "r")) == NULL) {

        MY_LOGE("Failed to open /vendor/res/images/watermark.rgba");

    }

    fread(mWatermarkRGBA, 1, watermarkSize, fp);

    fclose(fp);

    FUNCTION_OUT;

}

void WatermarkCapture::uninit() {

    FUNCTION_IN;

    free(mWatermarkRGBA);

    FUNCTION_OUT;

}

void WatermarkCapture::abort(vector <RequestPtr> &pRequests) {

    FUNCTION_IN;

    (void)pRequests;

    FUNCTION_OUT;

}

void WatermarkCapture::set(MINT32 iOpenId, MINT32 iOpenId2) {

    FUNCTION_IN;

    MY_LOGD("set openId:%d openId2:%d", iOpenId, iOpenId2);

    mOpenid = iOpenId;

    FUNCTION_OUT;

}

const WatermarkCapture::Property &WatermarkCapture::property() {

    FUNCTION_IN;

    static Property prop;

    static bool inited;

    if (!inited) {

        prop.mName = "TP_WATERMARK";

        prop.mFeatures = TP_FEATURE_WATERMARK;

        prop.mInPlace = MTRUE;

        prop.mFaceData = eFD_Current;

        prop.mPosition = 0;

        inited = true;

    }

    FUNCTION_OUT;

    return prop;

}

MERROR WatermarkCapture::negotiate(Selection &sel) {

    FUNCTION_IN;

    if (!mEnable) {

        MY_LOGD("Force off TP_WATERMARK");

        FUNCTION_OUT;

        return -EINVAL;

    }

    sel.mIBufferFull

            .setRequired(MTRUE)

            .addAcceptedFormat(eImgFmt_I420)

            .addAcceptedSize(eImgSize_Full);

    sel.mIMetadataDynamic.setRequired(MTRUE);

    sel.mIMetadataApp.setRequired(MTRUE);

    sel.mIMetadataHal.setRequired(MTRUE);

    sel.mOMetadataApp.setRequired(MTRUE);

    sel.mOMetadataHal.setRequired(MTRUE);

    FUNCTION_OUT;

    return OK;

}

MERROR WatermarkCapture::process(RequestPtr pRequest,

                               RequestCallbackPtr pCallback = nullptr) {

    FUNCTION_IN;

    WATERMARK_TRACE_CALL();

    MBOOL needRun = MFALSE;

    if (pRequest->mIBufferFull != nullptr && pRequest->mOBufferFull != nullptr) {

        IImageBuffer *pIBufferFull = pRequest->mIBufferFull->acquire();

        IImageBuffer *pOBufferFull = pRequest->mOBufferFull->acquire();

        if (pRequest->mIMetadataDynamic != nullptr) {

            IMetadata *meta = pRequest->mIMetadataDynamic->acquire();

            if (meta != NULL)

                MY_LOGD("[IN] Dynamic metadata count: %d", meta->count());

            else

                MY_LOGD("[IN] Dynamic metadata empty");

        }

        int frameNo = 0, requestNo = 0;

        if (pRequest->mIMetadataHal != nullptr) {

            IMetadata *pIMetataHAL = pRequest->mIMetadataHal->acquire();

            if (pIMetataHAL != NULL) {

                MY_LOGD("[IN] HAL metadata count: %d", pIMetataHAL->count());

                if (!tryGetMetadata<int>(pIMetataHAL, MTK_PIPELINE_FRAME_NUMBER, frameNo)) {

                    frameNo = 0;

                }

                if (!tryGetMetadata<int>(pIMetataHAL, MTK_PIPELINE_REQUEST_NUMBER, requestNo)) {

                    requestNo = 0;

                }

                MY_LOGD("frameNo: %d, requestNo: %d", frameNo, requestNo);

            } else {

                MY_LOGD("[IN] HAL metadata empty");

            }

        }

        if (pRequest->mIMetadataApp != nullptr) {

            IMetadata *pIMetadataApp = pRequest->mIMetadataApp->acquire();

            MINT32 mode = 0;

            if (!tryGetMetadata<MINT32>(pIMetadataApp, QXT_FEATURE_WATERMARK, mode)) {

                mode = 0;

            }

            needRun = mode == 1 ? 1 : 0;

        }

        MY_LOGD("needRun: %d", needRun);

        int width = pIBufferFull->getImgSize().w;

        int height = pIBufferFull->getImgSize().h;

        MINT inFormat = pIBufferFull->getImgFormat();

        if (needRun && inFormat == NSCam::eImgFmt_I420) {

            uint32_t currentTime = (NSCam::Utils::TimeTool::getReadableTime()) % 1000;

            time_t timep;

            time (&timep);

            char currentDate[20];

            strftime(currentDate, sizeof(currentDate), "%Y%m%d_%H%M%S", localtime(&timep));

            //dump input I420

            if (mDump) {

                char path[256];

                snprintf(path, sizeof(path), "/data/vendor/camera_dump/capture_in_frame%d_%dx%d_%s_%d.i420",

                    frameNo, width, height, currentDate, currentTime);

                pIBufferFull->saveToFile(path);

            }

            nsecs_t t1 = systemTime(CLOCK_MONOTONIC);

            if (mSrcRGBA == NULL) {

                mSrcRGBA = (unsigned char *) malloc(width * height * 4);

            }

            //convert I420 to RGBA

            libyuv::I420ToABGR((unsigned char *) (pIBufferFull->getBufVA(0)), width,

                               (unsigned char *) (pIBufferFull->getBufVA(1)), width >> 1,

                               (unsigned char *) (pIBufferFull->getBufVA(2)), width >> 1,

                               mSrcRGBA, width * 4,

                               width, height);

            nsecs_t t2 = systemTime(CLOCK_MONOTONIC);

            MY_LOGD("Prepare src cost %02ld ms", ns2ms(t2 - t1));

            Watermark::add(mSrcRGBA, width, height, mWatermarkRGBA, mWatermarkWidth, mWatermarkHeight, (width - mWatermarkWidth) / 2, (height - mWatermarkHeight) / 2);

            nsecs_t t3 = systemTime(CLOCK_MONOTONIC);

            MY_LOGD("Add watermark cost %02ld ms", ns2ms(t3 - t2));

            //convert RGBA to I420

            libyuv::ABGRToI420(mSrcRGBA, width * 4,

                               (unsigned char *) (pOBufferFull->getBufVA(0)), width,

                               (unsigned char *) (pOBufferFull->getBufVA(1)), width >> 1,

                               (unsigned char *) (pOBufferFull->getBufVA(2)), width >> 1,

                               width, height);

            nsecs_t t4 = systemTime(CLOCK_MONOTONIC);

            MY_LOGD("Copy in to out cost %02ld ms", ns2ms(t4 - t3));

            //dump output I420

            if (mDump) {

                char path[256];

                snprintf(path, sizeof(path), "/data/vendor/camera_dump/capture_out_frame%d_%dx%d_%s_%d.i420",

                    frameNo, width, height, currentDate, currentTime);

                pOBufferFull->saveToFile(path);

            }

            free(mSrcRGBA);

        } else {

            if (!needRun) {

                MY_LOGE("No need run, skip add watermark for capture.");

            } else if (inFormat != NSCam::eImgFmt_YV12) {

                MY_LOGE("Unsupported format, skip add watermark for capture.");

            } else {

                MY_LOGE("Unknown exception, skip add watermark for capture.");

            }

            memcpy((unsigned char *) (pOBufferFull->getBufVA(0)),

                   (unsigned char *) (pIBufferFull->getBufVA(0)),

                   pIBufferFull->getBufSizeInBytes(0));

            memcpy((unsigned char *) (pOBufferFull->getBufVA(1)),

                   (unsigned char *) (pIBufferFull->getBufVA(1)),

                   pIBufferFull->getBufSizeInBytes(1));

            memcpy((unsigned char *) (pOBufferFull->getBufVA(2)),

                   (unsigned char *) (pIBufferFull->getBufVA(2)),

                   pIBufferFull->getBufSizeInBytes(2));

        }

        pRequest->mIBufferFull->release();

        pRequest->mOBufferFull->release();

        if (pRequest->mIMetadataDynamic != nullptr) {

            pRequest->mIMetadataDynamic->release();

        }

        if (pRequest->mIMetadataHal != nullptr) {

            pRequest->mIMetadataHal->release();

        }

        if (pRequest->mIMetadataApp != nullptr) {

            pRequest->mIMetadataApp->release();

        }

    }

    if (pCallback != nullptr) {

        MY_LOGD("callback request");

        pCallback->onCompleted(pRequest, 0);

    }

    FUNCTION_OUT;

    return OK;

}

REGISTER_PLUGIN_PROVIDER(Yuv, WatermarkCapture);

新增

vendormediatekproprietaryhardwaremtkcam33rdpartycustomertp_watermarkWatermarkPreview.cpp

#include <mtkcam3/3rdparty/plugin/PipelinePluginType.h>

#include <mtkcam/utils/metadata/hal/mtk_platform_metadata_tag.h>

#include <mtkcam/utils/metadata/client/mtk_metadata_tag.h>

#include <cutils/properties.h>

#include <watermark.h>

#include <mtkcam/utils/std/Time.h>

#include <time.h>

#include <libyuv.h>

#include <dlfcn.h>

using NSCam::NSPipelinePlugin::Interceptor;

using NSCam::NSPipelinePlugin::PipelinePlugin;

using NSCam::NSPipelinePlugin::PluginRegister;

using NSCam::NSPipelinePlugin::Join;

using NSCam::NSPipelinePlugin::JoinPlugin;

using namespace NSCam::NSPipelinePlugin;

using NSCam::MSize;

using NSCam::MERROR;

using NSCam::IImageBuffer;

using NSCam::IMetadata;

using NSCam::Type2Type;

#ifdef LOG_TAG

#undef LOG_TAG

#endif // LOG_TAG

#define LOG_TAG "WatermarkPreview"

#include <log/log.h>

#include <android/log.h>

#define MY_LOGI(fmt, arg...)  ALOGI("[%s] " fmt, __FUNCTION__, ##arg)

#define MY_LOGD(fmt, arg...)  ALOGD("[%s] " fmt, __FUNCTION__, ##arg)

#define MY_LOGW(fmt, arg...)  ALOGW("[%s] " fmt, __FUNCTION__, ##arg)

#define MY_LOGE(fmt, arg...)  ALOGE("[%s] " fmt, __FUNCTION__, ##arg)

#define FUNCTION_IN   MY_LOGD("%s +", __FUNCTION__)

#define FUNCTION_OUT  MY_LOGD("%s -", __FUNCTION__)

template <class T>

inline bool

tryGetMetadata(IMetadata const *pMetadata, MUINT32 tag, T& rVal)

{

    if(pMetadata == nullptr) return MFALSE;

    IMetadata::IEntry entry = pMetadata->entryFor(tag);

    if(!entry.isEmpty())

    {

        rVal = entry.itemAt(0,Type2Type<T>());

        return true;

    }

    else

    {

#define var(v) #v

#define type(t) #t

        MY_LOGW("no metadata %s in %s", var(tag), type(pMetadata));

#undef type

#undef var

    }

    return false;

}

class WatermarkPreview : public JoinPlugin::IProvider {

public:

    typedef JoinPlugin::Property Property;

    typedef JoinPlugin::Selection Selection;

    typedef JoinPlugin::Request::Ptr RequestPtr;

    typedef JoinPlugin::RequestCallback::Ptr RequestCallbackPtr;

private:

    bool mDisponly = false;

    bool mInplace = false;

    int mOpenID1 = 0;

    int mOpenID2 = 0;

    MBOOL mEnable = 1;

    MBOOL mDump = 0;

    unsigned char *mSrcRGBA = nullptr;

    unsigned char *mWatermarkRGBA = nullptr;

    int mWatermarkWidth = 0;

    int mWatermarkHeight = 0;

public:

    WatermarkPreview();

    ~WatermarkPreview();

    void init();

    void uninit();

    void abort(std::vector <RequestPtr> &pRequests);

    void set(MINT32 openID1, MINT32 openID2);

    const Property &property();

    MERROR negotiate(Selection &sel);

    MERROR process(RequestPtr pRequest, RequestCallbackPtr pCallback);

private:

    MERROR getConfigSetting(Selection &sel);

    MERROR getP1Setting(Selection &sel);

    MERROR getP2Setting(Selection &sel);

};

WatermarkPreview::WatermarkPreview() {

    FUNCTION_IN;

    mEnable = property_get_bool("vendor.debug.camera.watermark.preview.enable", 1);

    mDump = property_get_bool("vendor.debug.camera.watermark.preview.dump", 0);

    FUNCTION_OUT;

}

WatermarkPreview::~WatermarkPreview() {

    FUNCTION_IN;

    FUNCTION_OUT;

}

void WatermarkPreview::init() {

    FUNCTION_IN;

    mWatermarkWidth = 180;

    mWatermarkHeight = 640;

    int watermarkSize = mWatermarkWidth * mWatermarkHeight * 4;

    mWatermarkRGBA = (unsigned char *) malloc(watermarkSize);

    FILE *fp;

    char path[256];

    snprintf(path, sizeof(path), "/vendor/res/images/watermark.rgba");

    if ((fp = fopen(path, "r")) == NULL) {

        MY_LOGE("Failed to open /vendor/res/images/watermark.rgba");

    }

    fread(mWatermarkRGBA, 1, watermarkSize, fp);

    fclose(fp);

    FUNCTION_OUT;

}

void WatermarkPreview::uninit() {

    FUNCTION_IN;

    free(mSrcRGBA);

    free(mWatermarkRGBA);

    FUNCTION_OUT;

}

void WatermarkPreview::abort(std::vector <RequestPtr> &pRequests) {

    FUNCTION_IN;

    (void)pRequests;

    FUNCTION_OUT;

}

void WatermarkPreview::set(MINT32 openID1, MINT32 openID2) {

    FUNCTION_IN;

    MY_LOGD("set openID1:%d openID2:%d", openID1, openID2);

    mOpenID1 = openID1;

    mOpenID2 = openID2;

    FUNCTION_OUT;

}

const WatermarkPreview::Property &WatermarkPreview::property() {

    FUNCTION_IN;

    static Property prop;

    static bool inited;

    if (!inited) {

        prop.mName = "TP_WATERMARK";

        prop.mFeatures = TP_FEATURE_WATERMARK;

        //prop.mInPlace = MTRUE;

        //prop.mFaceData = eFD_Current;

        //prop.mPosition = 0;

        inited = true;

    }

    FUNCTION_OUT;

    return prop;

}

MERROR WatermarkPreview::negotiate(Selection &sel) {

    FUNCTION_IN;

    MERROR ret = OK;

    if (sel.mSelStage == eSelStage_CFG) {

        ret = getConfigSetting(sel);

    } else if (sel.mSelStage == eSelStage_P1) {

        ret = getP1Setting(sel);

    } else if (sel.mSelStage == eSelStage_P2) {

        ret = getP2Setting(sel);

    }

    FUNCTION_OUT;

    return ret;

}

MERROR WatermarkPreview::process(RequestPtr pRequest, RequestCallbackPtr pCallback) {

    FUNCTION_IN;

    (void) pCallback;

    MERROR ret = -EINVAL;

    MBOOL needRun = MFALSE;

    IImageBuffer *in = NULL, *out = NULL;

    if (pRequest->mIBufferMain1 != NULL && pRequest->mOBufferMain1 != NULL) {

        in = pRequest->mIBufferMain1->acquire();

        out = pRequest->mOBufferMain1->acquire();

        int frameNo = 0, requestNo = 0;

        if (pRequest->mIMetadataHal1 != nullptr) {

            IMetadata *pIMetataHAL1 = pRequest->mIMetadataHal1->acquire();

            if (pIMetataHAL1 != NULL) {

                if (!tryGetMetadata<int>(pIMetataHAL1, MTK_PIPELINE_FRAME_NUMBER, frameNo)) {

                    frameNo = 0;

                }

                if (!tryGetMetadata<int>(pIMetataHAL1, MTK_PIPELINE_REQUEST_NUMBER, requestNo)) {

                    requestNo = 0;

                }

                pRequest->mIMetadataHal1->release();

                MY_LOGD("frameNo: %d, requestNo: %d", frameNo, requestNo);

            } else {

                MY_LOGD("HAL metadata empty");

            }

        }

        MY_LOGD("in[%d](%dx%d)=%p out[%d](%dx%d)=%p",

                in->getPlaneCount(), in->getImgSize().w, in->getImgSize().h, in,

                out->getPlaneCount(), out->getImgSize().w, out->getImgSize().h, out);

        if (pRequest->mIMetadataApp != nullptr) {

            IMetadata *pIMetadataApp = pRequest->mIMetadataApp->acquire();

            MINT32 mode = 0;

            if (!tryGetMetadata<MINT32>(pIMetadataApp, QXT_FEATURE_WATERMARK, mode)) {

                mode = 0;

            }

            needRun = mode == 1 ? 1 : 0;

            pRequest->mIMetadataApp->release();

        }

        MY_LOGD("needRun: %d", needRun);

        int width = in->getImgSize().w;

        int height = in->getImgSize().h;

        MINT inFormat = in->getImgFormat();

        if (needRun && inFormat == NSCam::eImgFmt_YV12) {

            uint32_t currentTime = (NSCam::Utils::TimeTool::getReadableTime()) % 1000;

            time_t timep;

            time (&timep);

            char currentDate[20];

            strftime(currentDate, sizeof(currentDate), "%Y%m%d_%H%M%S", localtime(&timep));

            //dump input YV12

            if (mDump) {

                char path[256];

                snprintf(path, sizeof(path), "/data/vendor/camera_dump/preview_in_frame%d_%dx%d_%s_%d.yv12",

                    frameNo, width, height, currentDate, currentTime);

                in->saveToFile(path);

            }

            nsecs_t t1 = systemTime(CLOCK_MONOTONIC);

            if (mSrcRGBA == NULL) {

                mSrcRGBA = (unsigned char *) malloc(width * height * 4);

            }

            //convert YV12 to RGBA

            libyuv::I420ToABGR((unsigned char *)(in->getBufVA(0)), width,

                               (unsigned char *)(in->getBufVA(2)), width >> 1,

                               (unsigned char *)(in->getBufVA(1)), width >> 1,

                               mSrcRGBA, width * 4,

                               width, height);

            nsecs_t t2 = systemTime(CLOCK_MONOTONIC);

            MY_LOGD("Prepare src cost %02ld ms", ns2ms(t2 - t1));

            Watermark::add(mSrcRGBA, width, height, mWatermarkRGBA, mWatermarkWidth, mWatermarkHeight, (width - mWatermarkWidth) / 2, (height - mWatermarkHeight) / 2);

            nsecs_t t3 = systemTime(CLOCK_MONOTONIC);

            MY_LOGD("Add watermark cost %02ld ms", ns2ms(t3 - t2));

            //convert RGBA to YV12

            libyuv::ABGRToI420(mSrcRGBA, width * 4,

                               (unsigned char *)(out->getBufVA(0)), width,

                               (unsigned char *)(out->getBufVA(2)), width >> 1,

                               (unsigned char *)(out->getBufVA(1)), width >> 1,

                               width, height);

            nsecs_t t4 = systemTime(CLOCK_MONOTONIC);

            MY_LOGD("Copy in to out cost %02ld ms", ns2ms(t4 - t3));

            //dump output YV12

            if (mDump) {

                char path[256];

                snprintf(path, sizeof(path), "/data/vendor/camera_dump/preview_out_frame%d_%dx%d_%s_%d.yv12",

                    frameNo, width, height, currentDate, currentTime);

                out->saveToFile(path);

            }

        } else {

            if (!needRun) {

                MY_LOGE("No need run, skip add watermark for preview.");

            } else if (inFormat != NSCam::eImgFmt_YV12) {

                MY_LOGE("Unsupported format, skip add watermark for preview.");

            } else {

                MY_LOGE("Unknown exception, skip add watermark for preview.");

            }

            memcpy((unsigned char *) (out->getBufVA(0)),

                   (unsigned char *)(in->getBufVA(0)),

                   in->getBufSizeInBytes(0));

            memcpy((unsigned char *) (out->getBufVA(1)),

                   (unsigned char *)(in->getBufVA(1)),

                   in->getBufSizeInBytes(1));

            memcpy((unsigned char *) (out->getBufVA(2)),

                   (unsigned char *)(in->getBufVA(2)),

                   in->getBufSizeInBytes(2));

        }

        pRequest->mIBufferMain1->release();

        pRequest->mOBufferMain1->release();

        ret = OK;

    }

    FUNCTION_OUT;

    return ret;

}

MERROR WatermarkPreview::getConfigSetting(Selection &sel) {

    MY_LOGI("max out size(%dx%d)",

            sel.mCfgInfo.mMaxOutSize.w, sel.mCfgInfo.mMaxOutSize.h);

    mDisponly = property_get_bool("vendor.debug.tpi.s.fb.disponly", 0);

    mInplace = mDisponly || property_get_bool("vendor.debug.tpi.s.fb.inplace", 0);

    sel.mCfgOrder = 3;

    sel.mCfgJoinEntry = eJoinEntry_S_YUV;

    sel.mCfgInplace = mInplace;

    sel.mCfgEnableFD = MTRUE;

    sel.mCfgRun = mEnable;

    sel.mIBufferMain1.setRequired(MTRUE);

    if (!mDisponly && property_get_bool("vendor.debug.tpi.s.fb.nv21", 0)) {

        sel.mIBufferMain1.addAcceptedFormat(NSCam::eImgFmt_NV21);

    }

    if (!mDisponly && property_get_bool("vendor.debug.tpi.s.fb.size", 0)) {

        sel.mIBufferMain1.setSpecifiedSize(sel.mCfgInfo.mMaxOutSize);

    }

    sel.mOBufferMain1.setRequired(MTRUE);

    sel.mIBufferMain1.addAcceptedFormat(NSCam::eImgFmt_YV12);

    sel.mIBufferMain1.addAcceptedSize(eImgSize_Full);

    IMetadata *meta = sel.mIMetadataApp.getControl().get();

    MY_LOGD("sessionMeta=%p", meta);

    return OK;

}

MERROR WatermarkPreview::getP1Setting(Selection &sel) {

    (void) sel;

    return OK;

}

MERROR WatermarkPreview::getP2Setting(Selection &sel) {

    MBOOL run = MTRUE;

    sel.mP2Run = run;

    return OK;

}

REGISTER_PLUGIN_PROVIDER(Join, WatermarkPreview);

将上面编译得到的 libwatermark.so 拷贝到对应文件夹

至此水印算法相关代码增加完成,接下来是多帧算法相关源码

新增 vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/customer/cp_tp_mfnr/ 文件夹

新增

vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/customer/cp_tp_mfnr/Android.mk

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_CHECK_ELF_FILES := false

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

新增

vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/customer/cp_tp_mfnr/include/mf_processor.h

头文件中的接口函数介绍:

setFrameCount: 没有实际作用,用于模拟设置第三方多帧算法的帧数。因为部分第三方多帧算法在不同场景下需要的帧数可能是不同的。

setParams: 也没有实际作用,用于模拟设置第三方多帧算法所需的参数。

addFrame: 用于添加一帧图像数据,用于模拟第三方多帧算法添加图像数据。

process: 将前面添加的4帧图像数据,缩小并拼接成一张原大小的图。

createInstance: 创建接口类对象。

#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

新增

vendormediatekproprietaryhardwaremtkcam33rdpartycustomercp_tp_mfnrMFNRImpl.cpp

主要函数介绍:

在property函数中feature类型设置成TP_FEATURE_MFNR,并设置名称、优先级、最大帧数等等属性。尤其注意mNeedRrzoBuffer属性,一般情况下,多帧算法必须要设置为MTRUE。

在negotiate函数中配置算法需要的输入、输出图像的格式、尺寸。注意,多帧算法有多帧输入,但是只需要一帧输出。因此这里设置了mRequestIndex == 0时才需要mOBufferFull。也就是只有第一帧才有输入和输出,其它帧只有输入。

另外,还在negotiate函数中获取上层传下来的metadata参数,根据参数决定算法是否运行。

在process函数中接入算法。第一帧时创建算法接口类对象,然后每一帧都调用算法接口函数addFrame加入,最后一帧再调用算法接口函数process进行处理并获取输出

#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);

将上面编译得到的 libmultiframe.so 拷贝到对应文件夹

至此多帧算法相关代码增加完成

注意:

MTK原文:

negotiate函数设置格式时,一个挂载点如果挂载多个同类型的plugin,则只有第一个 plugin 中的 negotiate 中的 input buffer 设定有效。

在YUVNode 下挂载单帧 YUV plugin时,一定要确保 MTK 平台的SWNR plugin 的 negotiate 直接返回不OK,不做任何 accepted format 等的设定。否则,可能会出现因 SWNR plugin和三方plugin negotiate时设定的 accepted format 不一致而导致的三方 plugin 拿不到它想要的 format 的buffer。

vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/mtk/swnr/SWNRImpl.cpp

@@ -391,7 +391,8 @@ negotiate(Selection& sel)

     sel.mOMetadataApp.setRequired(false);

     sel.mOMetadataHal.setRequired(true);

-    return OK;

+    //return OK;^M

+    return -EINVAL;//cczheng^M

 }

最终vendor.img需要的目标共享库是libmtkcam_3rdparty.customer.so。因此,我们还需要修改Android.mk,

使模块 libmtkcam_3rdparty.customer 依赖 libmtkcam.plugin.tp_watermark

模块 libmtkcam_3rdparty.customer 依赖 libmtkcam.plugin.tp_mfnr

vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/customer/Android.mk

@@ -76,6 +76,19 @@ LOCAL_WHOLE_STATIC_LIBRARIES += libmtkcam.plugin.tp_zoomfusion

 #

 LOCAL_SHARED_LIBRARIES += libcam.iopipe

 endif

+

+ifeq ($(QXT_WATERMARK_SUPPORT), yes)

+LOCAL_SHARED_LIBRARIES += libwatermark

+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

+

 #

 LOCAL_SHARED_LIBRARIES += libfeature.stereo.provider

 #

预置水印文件

device/mediateksample/k62v1_64_bsp/device.mk

+++ b/alps/device/mediateksample/k62v1_64_bsp/device.mk

@@ -43,6 +43,9 @@ endif

 PRODUCT_COPY_FILES += frameworks/native/data/etc/android.hardware.usb.host.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.usb.host.xml

+ifeq ($(QXT_WATERMARK_SUPPORT),yes)

+PRODUCT_COPY_FILES += vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/customer/tp_watermark/res/watermark.rgba::$(TARGET_COPY_OUT_VENDOR)/res/images/watermark.rgba

+endif

camera hal进程为mtk_camera_hal,它要读取/vendor/res/images/watermark.rgba,读取需要vendor_file SELinux权限。这里为mtk_camera_hal配置SELinux权限:

device/mediatek/sepolicy/bsp/non_plat/mtk_hal_camera.te

@@ -93,7 +93,7 @@ set_prop(mtk_hal_camera, vendor_mtk_camera_prop)

 allow mtk_hal_camera teei_client_device:chr_file rw_file_perms;

 allow mtk_hal_camera mdla_device:chr_file rw_file_perms;

+allow mtk_hal_camera vendor_file:file { read getattr open };

 #Date: 2019/11/11

移除MTK示例的MFNR算法

一般情况下,MFNR 算法同一时间只允许运行一个。因此,需要移除 MTK 示例的 MFNR 算法。我们可以使用宏控来移除,这里就简单粗暴,直接注释掉了。

vendor/mediatek/proprietary/hardware/mtkcam3/3rdparty/mtk/Android.mk

@@ -146,7 +146,7 @@ LOCAL_SHARED_LIBRARIES += libfeature.stereo.provider

 LOCAL_SHARED_LIBRARIES += liblpcnr

 #-----------------------------------------------------------

 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

添加metadata是为了让APP层能够通过metadata传递相应的参数给HAL层。APP层是通过CaptureRequest.Builder.set(@NonNull Key key, T value)来设置参数的。

由于我们是自定义的feature,无法复用MTK提供的metadata,因此,我们需要自定义metadata。

vendor/mediatek/proprietary/hardware/mtkcam/include/mtkcam/utils/metadata/client/mtk_metadata_tag.h

@@ -94,6 +94,7 @@ typedef enum mtk_camera_metadata_section {

     MTK_SMVR_FEATURE                = 15,

     MTK_SINGLEHW_SETTING            = 16,

     MTK_ABF_FEATURE                 = 17,

+    QXT_FEATURE                     = 18,//cczheng

     MTK_VENDOR_SECTION_COUNT,

 } mtk_camera_metadata_section_t;

@@ -155,6 +156,7 @@ typedef enum mtk_camera_metadata_section_start {

     MTK_SMVR_FEATURE_START                      = (MTK_SMVR_FEATURE + MTK_VENDOR_TAG_SECTION) << 16,

     MTK_SINGLEHW_SETTING_START                  = (MTK_SINGLEHW_SETTING + MTK_VENDOR_TAG_SECTION) << 16,

     MTK_ABF_FEATURE_START                       = (MTK_ABF_FEATURE + MTK_VENDOR_TAG_SECTION)   << 16,

+    QXT_FEATURE_START                           = (QXT_FEATURE + MTK_VENDOR_TAG_SECTION) << 16,//cczheng

 } mtk_camera_metadata_section_start_t;

@@ -754,6 +756,10 @@ typedef enum mtk_camera_metadata_tag {

     MTK_ABF_FEATURE_ABF_RESULT,

     MTK_ABF_FEATURE_AVAILABLE_ABF_MODES,

     MTK_ABF_FEATURE_END,

+

+    QXT_FEATURE_WATERMARK = QXT_FEATURE_START,

+    QXT_FEATURE_MFNR,//cczheng

+    QXT_FEATURE_END,//cczheng

 } mtk_camera_metadata_tag_t;

 /**

vendor/mediatek/proprietary/hardware/mtkcam/include/mtkcam/utils/metadata/client/mtk_metadata_tag_info.inl

@@ -92,6 +92,8 @@ _IMP_SECTION_INFO_(MTK_HEIC,                        "mtk.heic")

 _IMP_SECTION_INFO_(MTK_HEIC_INFO,                   "mtk.heic.ifno")

 _IMP_SECTION_INFO_(MTK_IOPIPE_INFO,                 "mtk.iopipe.info")

 _IMP_SECTION_INFO_(MTK_HAL_INFO,                    "mtk.hal.info")

+_IMP_SECTION_INFO_(QXT_FEATURE,                     "com.qxt.camera")

+//cczheng

 /******************************************************************************

  *

@@ -106,6 +108,12 @@ _IMP_TAG_INFO_( MTK_COLOR_CORRECTION_ABERRATION_MODE,

                 MUINT8,     "aberrationMode")

 _IMP_TAG_INFO_( MTK_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,

                 MUINT8,     "availableAberrationModes")

+

+_IMP_TAG_INFO_( QXT_FEATURE_WATERMARK,

+                MINT32,     "watermark")

+_IMP_TAG_INFO_( QXT_FEATURE_MFNR,

+                MINT32,     "mfnr")

+

 //

 _IMP_TAG_INFO_( MTK_CONTROL_AE_ANTIBANDING_MODE,

                 MUINT8,     "aeAntibandingMode")

vendor/mediatek/proprietary/hardware/mtkcam/utils/metadata/vendortag/VendorTagTable.h

@@ -547,6 +547,19 @@ static auto& _FlashFeature_()

      //

      return sInst;

 }

+//cczheng

+static auto& _QxtFeature_()

+{

+    static const std::map<uint32_t, VendorTag_t>

+    sInst = {

+        _TAG_(QXT_FEATURE_WATERMARK,

+            "watermark",   TYPE_INT32),

+        _TAG_(QXT_FEATURE_MFNR,

+            "mfnr",   TYPE_INT32),

+     };

+     //

+     return sInst;

+}

 static auto& _SingleHWSetting_()

 {

@@ -668,6 +681,10 @@ static auto& getGlobalSections()

                     MTK_ABF_FEATURE_START,

                     MTK_ABF_FEATURE_END,

                     _ABFFeature_() ),

+        _SECTION_( "com.qxt.camera",

+                    QXT_FEATURE_START,

+                    QXT_FEATURE_END,

+                    _QxtFeature_() ),

     };

     // append custom vendor tags sections to mtk sections

vendor/mediatek/proprietary/hardware/mtkcam/utils/metastore/metadataprovider/constructStaticMetadata.cpp

@@ -1325,6 +1325,20 @@ updateData(IMetadata &rMetadata)

         rMetadata.update(availReqEntry.tag(), availReqEntry);

     }

+//cczheng 

+#if 1

+    {

+        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

+

     // update multi-cam feature mode to static metadata

     // vendor tag

     {

好了,搞到这一步。大功告成了,先 make 一把,刷机看效果

最后

由于 watermark.rgba 没找到源文件,我从其它地方搞了个所以水印显示时宽高不太对,就没正确显示,具体效果我没仔细调整。

另外既然系统已经预制了这两个算法,所有 app 均可调用,那么可以在系统相机中也增加两按钮,加载这两算法,也算是丰富了

原始相机单一风格,有兴趣的朋友可以自己去加下,毕竟普通 app 的代码已经提供了。


版权声明:本文为CSDN博主「cczhengv」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/u012932409/article/details/120263991



0条评论

© 2021 芯缘异码. Powered by Typecho