【Camera专题】HAL层- 以SO库的方式集成第三方算法

系列文章

动手入门第三方算法集成系列:
【Camera专题】HAL层- 实现第三方算法并集成到Android系统
【Camera专题】HAL层- 以SO库的方式集成第三方算法

一、前言

上篇文章,我们自己实现了算法,并直接集成到系统中。
但是,我们集成第三方算法的时候,厂商给的是so库,
具体实现你是看不到的,因此,我们也以so库的方式进行集成。

本文知识点:

1.算法集成的步骤
参考我同事的文章: Android调用第三方C++算法库
2.如何生成so库
融合到知识点3里一起写
3.动手实践

二、动手实践

1.把自己写的算法编译成so库

a.创建文件

external/hello_algo/

  • hello_algo.c
    这里是自己实现的算法:Yuv2Gray
  • Android.mk
    这里面指定编译规则

hello_algo.c

#include 

void YUV2Gray(unsigned char* srcYuv,int w,int h) {
    int mid = w*h/2;
    unsigned char* startP = srcYuv + mid;
    printf("zcf YUV2Gray is call\n");
    for(int i=0;i<mid;i++) {
        *startP = 0x80;//128
        startP++;
    }   
}

这个算法很简单,就不多逼逼了!
Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
//库的名称:lib_helloalgo
LOCAL_MODULE := lib_helloalgo
LOCAL_SRC_FILES := $(call all-subdir-c-files)
#指定生成so库
include $(BUILD_SHARED_LIBRARY)

b.编译生成so库
编译命令:
mmm external/hello_algo/
编译完成后,会在以下路径生成so库
【Camera专题】HAL层- 以SO库的方式集成第三方算法_第1张图片

库的名称就是我们在Android.mk里面指定的名称:
LOCAL_MODULE := lib_helloalgo

到此,我们自己写的算法就变成so库了。

2.以so库的方式集成第三方算法

算法库名称:lib_helloalgo.so
头文件:hello_algo.h
可调用方法:YUV2Gray

a.在Android源码中预编译算法库

创建目录hello_algo及子文件

h a r d w a r e / q c o m / c a m e r a / Q C a m e r a 2 / H A L / h e l l o _ a l g o \color{red}{hardware/qcom/camera/QCamera2/HAL/hello\_algo} hardware/qcom/camera/QCamera2/HAL/hello_algo

│─Android.mk
│
├─include/  
│── hello_algo.h
│
├─lib/
│── lib_helloalgo.so

Android.mk内容

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
#默认不会加上lib前缀
LOCAL_MODULE := lib_helloalgo
#不管是release还是debug版本, 都编译这个模块
LOCAL_MODULE_TAGS := optional
#so文件路径以及名字 
LOCAL_SRC_FILES := lib/lib_helloalgo.so
LOCAL_MODULE_STEM := $(LOCAL_MODULE)
#需要指定文件后缀
LOCAL_MODULE_SUFFIX := $(suffix $(LOCAL_SRC_FILES))
#编译32位算法库
LOCAL_MULTILIB := 32
#表明预编译的是动态库
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
include $(BUILD_PREBUILT)

hello_algo.h内容

extern "C" void YUV2Gray(unsigned char* srcYuv,int w,int h);

注意前面一点要加入extern “C”,不然编译的时候,会报错:undefined reference to xxx

b.在调用的模块Android.mk中加入依赖库
h a r d w a r e / q c o m / c a m e r a / Q C a m e r a 2 / H A L / A n d r o i d . m k \color{red}{hardware/qcom/camera/QCamera2/HAL/Android.mk} hardware/qcom/camera/QCamera2/HAL/Android.mk

# 表明引入的头文件
++LOCAL_C_INCLUDES += $(LOCAL_PATH)/hello_algo/include
# 表明当前HAL模块依赖我们要调用的算法库
++LOCAL_SHARED_LIBRARIES += lib_helloalgo
#在最末尾出引入我们预编译的Android.mk, 不然默认系统不会执行我们写的预编译用的Android.mk
++include $(LOCAL_PATH)/hello_algo/Android.mk

c.调用算法库
h a r d w a r e / q c o m / c a m e r a / Q C a m e r a 2 / H A L / Q C a m e r a 2 H W I C a l l b a c k s . c p p \color{red}{hardware/qcom/camera/QCamera2/HAL/QCamera2HWICallbacks.cpp} hardware/qcom/camera/QCamera2/HAL/QCamera2HWICallbacks.cpp

  #include 
  #include 
  #include "QCamera2HWI.h"
//引入头文件
++#include "hello_algo.h"

void QCamera2HardwareInterface::preview_stream_cb_routine(mm_camera_super_buf_t *super_frame,
                                                          QCameraStream * stream,
                                                          void *userdata)
{
    ATRACE_CALL();
    CDBG("[KPI Perf] %s : BEGIN", __func__);
    int err = NO_ERROR;
    QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata;
    QCameraGrallocMemory *memory = (QCameraGrallocMemory *)super_frame->bufs[0]->mem_info;

    if (pme == NULL) {
        ALOGE("%s: Invalid hardware object", __func__);
        free(super_frame);
        return;
    }    
    if (memory == NULL) {
        ALOGE("%s: Invalid memory object", __func__);
        free(super_frame);
        return;
    }    

    mm_camera_buf_def_t *frame = super_frame->bufs[0];
    if (NULL == frame) {
        ALOGE("%s: preview frame is NLUL", __func__);
        free(super_frame);
        return;
    }    
      //获取YUV数据地址
++    unsigned char* yuv = (unsigned char *)frame->buffer;
++    cam_dimension_t dim; 
      //获取实际宽高
++    stream->getFrameDimension(dim);
++    cam_frame_len_offset_t offset;
	  //获取对齐后宽高
++    stream->getFrameOffset(offset);
++    ALOGE("%s: zcf frame_len=%d dim.w=%d,diw.h=%d,对齐后w=%d,高=%d",
		__func__,
		frame->frame_len,dim.width,dim.height,
		offset.mp[0].stride,offset.mp[0].scanline);

      //获取调用第三方算法
++    YUV2Gray(yuv,offset.mp[0].offset.mp[0].scanline);
···
    }

我们在代码里并没有YUV2Gray函数的实现,而是引入了头文件hello_algo.h
最终会调用到lib_helloalgo.so里面的实现!

编译
你也可以编译整个系统:
make -j32 2>&1 | tee mlog
然后刷机验证。
或者
mmm hardware/qcom/camera/QCamera2/HAL/
编译完成后会在以下目录:
out/target/product/【项目名】/system/lib/hw
生成camera.msm8909.so库

adb push camera.msm8909.so system/lib/hw
adb push lib_helloalgo.so system/lib
然后重启生效

三、结果

【Camera专题】HAL层- 以SO库的方式集成第三方算法_第2张图片

可以看到,屏幕的一半变成了灰色!

学到这,以so库的形式集成第三方算法就ok了!
你应该清楚 第三方算法集成 的基本套路了!
后续有更好的干货,再分享吧!

Stay Hungry,Stay Foolish!

你可能感兴趣的:(Camera专题)