Android Camera预览/录像功耗偏高优化方法

Camera功耗偏高 :

一般优化为:

1. 降低CPUloading

Android Camera预览/录像功耗偏高优化方法

2. 在不造成卡顿的情况下降低CPU的频率

另外,请确认测试使用的是user版本,userdebug版本的camera默认全程高频

下面分别介绍

> 1.降低CPU Loading

先抓到 Camera 进程的各线程占用,找出消耗最大的几个线程,看能否优化。

一般来说会看到几个算法的线程,此时可以内部确认是否可以关闭一些不需要的算法node,比如如果不需要人脸识别就可以关闭FD。

如果项目上要求算法不能关闭,那就看能否进行隔帧处理。

top查看各进程、各线程cpu占用

查看进程:top

查看线程:top -H -p

top输出某个特定进程并检查该进程内运行的线程状况

> 2.在不造成卡顿的情况下降低CPU的频率

平台camera预览的 power 逻辑是 :

刚进入camera,使用high_perf高频, 出约35帧后,进入lowpower低频 , 关相机时进入high_perf高频

平台Camera Capture 的power逻辑是:

拍照时进入high_perf提频 , 在拍照完成,大图返回后,进入perview的频点(lowpower)

camera的power策略总体逻辑为:

在相机对性能要求高的场景(如打开、关闭相机,拍照等)进行提频,以减少卡顿情况的发生;

在预览等对性能要求没那么高的场景使用低频,以控制整体功耗。

一般录像时4k60fps时才就会进入高频策略,详情可查阅基线 adjustprviewperformance() 函数(A11~A14不同安卓版本的位置可能不同,但都查这个函数即可)。

即一般预览、录像使用的是camera_lowpower策略,修改camera_lowpower 的各核频率范围即可
power_scene_config.xml
        
	
	      小核最小频率
              小核最大频率
              大核最小频率(9863等平台为policy4)
              大核最大频率
               大核提频幅度
              小核提频幅度
        

freq_margin 指提频,例如调频时,计算目标频率的方式是max_freq * cpu使用率,引入freq_margin 后,假设freq_margin是30,计算方式变成了max_freq * ( 1 + 30% ) * cpu使用率, freq_margin 的取值范围是[-100, 100]。

> 3.针对某个三方应用设置cpu策略 :

 

A14示例:

① vendor/sprd/modules/libcamera/idispatch/android/Camera3Adapter.cpp

48  static TopAppS topAppList[] = {
49      { TOP_APP_NONE, "com.android.camera2" },
50      { TOP_APP_WECHAT, "com.tencent.mm" },
51      // { TOP_APP_WTFACTORY, ""},
52      { TOP_APP_QQ, "com.tencent.mobileqq"},
53      { TOP_APP_FACEBOOK, "com.facebook.katana"},
54      { TOP_APP_INSTAGRAM, "com.instagram.android"},
55      { TOP_APP_MESSENGER, "com.facebook.orca"},
56      { TOP_APP_SNAPCHAT, "com.snapchat.android"},
57      { TOP_APP_WHATSAPP, "com.whatsapp"},
> ++++++    { TOP_APP_GPULUMERA, "com.joeware.android.gpulumera"},

② vendor/sprd/modules/libcamera/common/inc/cmr_common.h

2233      //for some thirdparty camera apps
2234      TOP_APP_MTXX       = 30,
2235      TOP_APP_MEIYAN,
2236      TOP_APP_FACEU,
2237      TOP_APP_LITE,
2238      TOP_APP_WUTA,
2239      TOP_APP_DOUBTNUT,
2240      TOP_APP_CALI,
2241      TOP_APP_TWITTER,
>++++++       TOP_APP_GPULUMERA

③ vendor/sprd/modules/libcamera/hal3_2v7/SprdCamera3Setting.cpp

9916  int SprdCamera3Setting::get3rdAppSceneLevel(SessionParam mSessionParam) {
9917      int level = 0;
9918      char macro_3rd[16] = "false";
9919      char macro_9863t_3rd[16] = "false";
9920      lwp::ConfigurationManager::getTarget("CONFIG_CAMERA_3RDAPP_SATISFYPERF", macro_3rd);
9921      lwp::ConfigurationManager::getTarget("CONFIG_CAMERA_9863T_POWERHINT", macro_9863t_3rd);
9922      if (mSessionParam.mTopAppId == TOP_APP_WECHAT) {
9923          level = CAM_PERFORMANCE_LEVEL_7;
9924      } else if (mSessionParam.mTopAppId != 0 || mSessionParam.sceneMode == CAM_SCENE_MODE_THIRDPARTY) {
9925          if (!(strcmp("true", macro_3rd))) {
9926              level = CAM_PERFORMANCE_LEVEL_4;
9927          } else {
9928              if (!(strcmp("true", macro_9863t_3rd)) && mSessionParam.mTopAppId > 0) {
9929                  level = CAM_PERFORMANCE_LEVEL_14;
9930              } else if (!(strcmp("true", macro_9863t_3rd)) && mSessionParam.mTopAppId < 0) {
9931                  level = CAM_PERFORMANCE_LEVEL_4;
9932              } else {
9933                  level = CAM_PERFORMANCE_LEVEL_6;
9934              }
9935          }
9936      }
//++++++++++++++++参考添加以下code
if(mSessionParam.mTopAppId ==TOP_APP_GPULUMERA){
level = CAM_PERFORMANCE_LEVEL_3;
HAL_LOGD("3RD_APP CAM_PERFORMANCE_LEVEL_3");
}
//++++++++++++++++
9937      return level;
9938  }

A13示例:

① vendor/sprd/modules/libcamera/hal3_2v6/SprdCamera3Setting.cpp
162 static TopAppS topAppList[] = {
163     { TOP_APP_NONE, "com.android.camera2" },
164     { TOP_APP_WECHAT, "com.tencent.mm" },
165     // { TOP_APP_WTFACTORY, ""},
166     { TOP_APP_QQ, "com.tencent.mobileqq"},
167     { TOP_APP_FACEBOOK, "com.facebook.katana"},
168     { TOP_APP_INSTAGRAM, "com.instagram.android"},
169     { TOP_APP_MESSENGER, "com.facebook.orca"},
170     { TOP_APP_SNAPCHAT, "com.snapchat.android"},
171     { TOP_APP_WHATSAPP, "com.whatsapp"},
172     { TOP_APP_QQINT, "com.tencent.mobileqqi"},
173     { TOP_APP_READYAPP, "com.google.android.apps.tachyon.readyapp"},
174     { TOP_APP_CAMERAGO, "com.google.android.apps.cameralite"},
>+++     { TOP_APP_VOLTE, "xxxxxxx"},

② vendor/sprd/modules/libcamera/common/inc/cmr_common.h
1833 enum top_app_id {
1834     //set other thirdparty apps besides the list to -1
1835     TOP_APP_NONE      = 0,
1836     TOP_APP_WECHAT    = (1 << 0),
1837     TOP_APP_WTFACTORY = (1 << 1),
1838     TOP_APP_QQ        = (1 << 2),
1839     TOP_APP_FACEBOOK  = (1 << 3),
1840     TOP_APP_INSTAGRAM = (1 << 4),
1841     TOP_APP_MESSENGER = (1 << 5),
1842     TOP_APP_SNAPCHAT  = (1 << 6),
1843     TOP_APP_WHATSAPP  = (1 << 7),
1844     TOP_APP_QQINT     = (1 << 8),
1845     TOP_APP_READYAPP  = (1 << 9),
1846     TOP_APP_CAMERAGO  = (1 << 10),
>+++     TOP_APP_VOLTE     = (1 << 11),
 
 
③ vendor/sprd/modules/libcamera / hal3_2v6/SprdCamera3OEMIf.cpp
void SprdCamera3OEMIf::adjustPreviewPerformance(uint32_t frame_num,
                                               const SPRD_DEF_Tag *sprddefInfo) {
   if (!isCapturing() && mIsPowerhintWait && !mIsAutoFocus) {
           if ((int)(frame_num - mStartFrameNum) > CAM_POWERHINT_WAIT_COUNT) {
               if (sprddefInfo->top_app_id == -2)
                   goto exit;
               if (getAppSceneLevel(mSprdAppmodeId) == CAM_PERFORMANCE_LEVEL_4 ||
                   getScenePerfLevel() == CAM_PERFORMANCE_LEVEL_4) {
                   setCamPreformaceScene(CAM_PERFORMANCE_LEVEL_4);
               } else if (getAppSceneLevel(mSprdAppmodeId) == CAM_PERFORMANCE_LEVEL_5 ||
                          getScenePerfLevel() == CAM_PERFORMANCE_LEVEL_5) {
                   setCamPreformaceScene(CAM_PERFORMANCE_LEVEL_5);
               } else if (getAppSceneLevel(mSprdAppmodeId) == CAM_PERFORMANCE_LEVEL_6 ||
                          getScenePerfLevel() == CAM_PERFORMANCE_LEVEL_6) {
                   setCamPreformaceScene(CAM_PERFORMANCE_LEVEL_6);
               } else if (getAppSceneLevel(mSprdAppmodeId) == CAM_PERFORMANCE_LEVEL_7 ||
                          getScenePerfLevel() == CAM_PERFORMANCE_LEVEL_7) {
                   setCamPreformaceScene(CAM_PERFORMANCE_LEVEL_7);
               } else if (getAppSceneLevel(mSprdAppmodeId) == CAM_PERFORMANCE_LEVEL_3 ||
                          getScenePerfLevel() == CAM_PERFORMANCE_LEVEL_3) {
                   setCamPreformaceScene(CAM_PERFORMANCE_LEVEL_3);
               } else if (getAppSceneLevel(mSprdAppmodeId) == CAM_PERFORMANCE_LEVEL_1 ||
                          getScenePerfLevel() == CAM_PERFORMANCE_LEVEL_1) {
                   setCamPreformaceScene(CAM_PERFORMANCE_LEVEL_1);
               }
               mIsPowerhintWait = 0;
           }
   }
>+++ if(mTopAppId == TOP_APP_VOLTE) {
>+++     setCamPreformaceScene(CAM_PERFORMANCE_LEVEL_1);
>+++     HAL_LOGD("TOP_APP_VOLTE,SET CAM_PERFORMANCE_LEVEL_1");
>+++   }
 
   return;
exit:
   setCamPreformaceScene(CAM_PERFORMANCE_LEVEL_6);
   mIsPowerhintWait = 0;
   return;
 
}

> 4.常用功耗优化方案:

① FD隔帧(Face Detect)

② PD隔帧(PDAF)

③ AWB隔帧

④ LSC隔帧

①FD隔帧(Face Detect)

 

A13\A14:

--- a/ips/swpool/facedetection/facedetection2.0/FaceDetectSDKNode.cpp
+++ b/ips/swpool/facedetection/facedetection2.0/FaceDetectSDKNode.cpp
@@ -418,11 +418,13 @@ void FaceDetectSDKNode::process(const std::string &port, data_type job) {
    }
    /* scaler end */
    ratio = (float)src.size.width / (float)dst.size.width;
-
-   if (fd_process(param, request, dst, ratio)) {
-       LOGE("fd_process fail");
+   if (mFDhandle.frame_id % 2 == 0)
+   {
+       if (fd_process(param, request, dst, ratio))
+       {
+           LOGE("fd_process fail");
+       }
    }

②PD隔帧(PDAF)

分为V3和V4两个算法版本,可通过log确认算法版本,例如:

PDAF_Algo_new_version: CAM_ALGO_3A_PD_4.0.0.202211280940

V14 版本修改:
vendor/sprd/modules/libcamera/ispalg/pdaf/sprd/pd4.x/pdaf_sprd_adpt_v2.c
static cmr_s32 sprd_pd_adpt_v2_process(cmr_handle adpt_handle, void *in, void *out)
{
.......
   void *pInPhaseBuf_left = NULL;
   void *pInPhaseBuf_right = NULL;
   cmr_u16 *pInPhaseBuf_Type2 = NULL;
   cmr_u8 *pInPhaseBuf_Dual_PD = NULL;
   struct af_pd2hybrid_info2 pd_result2;
 
+++   cxt->frame_id = proc_in->frame_id;
+++   //for pd type2 skip
+++   if ((0 == cxt->frame_id % 2)
+++       && (cxt->pd_type == PDAF_SENSOR_TYPE2))
+++   {
+++       return ISP_SUCCESS;
 +++  }
 
   memset(&callback_in, 0, sizeof(callback_in));
   memset(&calc_out, 0, sizeof(struct pd_calc_out));
 
   cxt->is_busy = 1;
----   cxt->frame_id = proc_in->frame_id;
 
   pd_sprd_adpt_get_af_info(cxt);

V3版本修改:

diff --git a/camdrv/isp2.6/middleware/isp_alg_fw.c b/camdrv/isp2.6/middleware/isp_alg_fw.c
index 61f1834..f7f85cd 100755
--- a/camdrv/isp2.6/middleware/isp_alg_fw.c
+++ b/camdrv/isp2.6/middleware/isp_alg_fw.c
@@ -5920,6 +5920,7 @@
 	u_addr = statis_info->uaddr;
 	pdaf_param_in.u_addr = statis_info->uaddr;
 	pdaf_param_in.u_addr_right = statis_info->uaddr + offset;
+	pdaf_param_in.frame_id = statis_info->frame_id;
 	ISP_LOGV("addr 0x%lx, addr1 0x%lx, offset %x\n", statis_info->uaddr, pdaf_param_in.u_addr_right, offset);
 
 	switch (cxt->pdaf_cxt.pdaf_support) {

diff --git a/ispalg/pdaf/inc/pdaf_ctrl.h b/ispalg/pdaf/inc/pdaf_ctrl.h
index 869c61c..eb50390 100755
--- a/ispalg/pdaf/inc/pdaf_ctrl.h
+++ b/ispalg/pdaf/inc/pdaf_ctrl.h
@@ -117,6 +117,7 @@
 	cmr_uint u_addr;
 	cmr_uint u_addr_right;
 	cmr_uint datasize;
+	cmr_uint frame_id;
 };
 
 struct pdaf_ctrl_process_out {
diff --git a/ispalg/pdaf/sprd/pdaf_sprd_adpt.c b/ispalg/pdaf/sprd/pdaf_sprd_adpt.c
index 122b1b9..d89d38a 100755
--- a/ispalg/pdaf/sprd/pdaf_sprd_adpt.c
+++ b/ispalg/pdaf/sprd/pdaf_sprd_adpt.c
@@ -585,6 +585,13 @@
 		ret = ISP_PARAM_NULL;
 		return ret;
 	}
+	cxt->frame_id = proc_in->frame_id;
+  //for pd type2 skip
+  if ((0 == cxt->frame_id % 2)
+    && (cxt->pdaf_type == PDAF_SENSOR_TYPE2))
+  {
+    return ISP_SUCCESS;
+  }
 
 	ISP_CHECK_HANDLE_VALID(adpt_handle);
 	memset(&callback_in, 0, sizeof(callback_in));
 

③ AWB隔帧

Awb隔帧:将tunning参数中awb项的calculation interval改为2,即每两帧计算一次。

将tunning参数中awb项的calculation interval改为2,即每两帧计算一次

④ LSC隔帧

lsc隔帧:需要修改tuning参数alsc模块的calc_freq 为3。

版权声明:如无特殊标注,文章均来自网络,本站编辑整理,转载时请以链接形式注明文章出处,请自行分辨。

本文链接:https://www.shbk5.com/dnsj/75211.html