android camera API1调用camera HAL3流程学习总结_hal1 hal3,2024年最新字节物联网嵌入式开发高级岗

121 阅读4分钟
            \*client = new CameraDeviceClient(.....);
        }
        break;
      default:
        // Should not be reachable
        ALOGE("Unknown camera device HAL version: %d", deviceVersion);
        .....
    }

}


通过上述代码分析发现`API1+HAL3`对用的client是`Camera2Client`  
 其类图如下:  
 ![在这里插入图片描述](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/0c5692114c4145b0ab9a7ea996291d67~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5py65Zmo5a2m5Lmg5LmL5b-DQUk=:q75.awebp?rk3s=f64ab15b&x-expires=1771251427&x-signature=dPii81c64KGDiQAMrYGszZ%2FWYsI%3D)  
 从上边看`Camera2Client`继承实现了`ICamera`定义的camera API1接口,但是其内部的成员变量mDevice是`Camera3Device 类型,其是针对HAL3设计的,其类的备注如下:



/** * CameraDevice for HAL devices with version CAMERA_DEVICE_API_VERSION_3_0 or higher. */ class Camera3Device : public CameraDeviceBase, virtual public hardware::camera::device::V3_2::ICameraDeviceCallback, private camera3_callback_ops


`Camera3Device`类图如下:


![在这里插入图片描述](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/d911aa99f58040c3a22582cac294d8bc~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5py65Zmo5a2m5Lmg5LmL5b-DQUk=:q75.awebp?rk3s=f64ab15b&x-expires=1771251427&x-signature=%2B0p%2B6e9HSeOTgnt3AJLLY4s02zQ%3D)  
 `Camera3Device`内部类`HalInterface`中的`sp<hardware::camera::device::V3_2::ICameraDeviceSession>mHidlSession`成员变量,是在opencamera是获取的对象,之后所有的`constructDefaultRequestSettings,configureStreams`等操作,都是通过该对象与HAL3进行通信完成的。  
 下边给出ICameraDeviceSession类图:  
 ![在这里插入图片描述](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/cc42438f6af54222a531fb52ba901b3a~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5py65Zmo5a2m5Lmg5LmL5b-DQUk=:q75.awebp?rk3s=f64ab15b&x-expires=1771251427&x-signature=aL5D17%2BORsZa%2F0fIHZig1DH4m8w%3D)  
 该类是定义在`hardware\interfaces\camera\device`中,是cameraservice与cameraprovider通信的接口。  
 **下边分析 openCamera具体流程**  
 ![在这里插入图片描述](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/201ac950d7d249d7b8e7b3eb590a1603~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5py65Zmo5a2m5Lmg5LmL5b-DQUk=:q75.awebp?rk3s=f64ab15b&x-expires=1771251427&x-signature=QRP1VkiIu3QL2%2Fg2flflyYVG5W0%3D)  
 从流程图上看,opencamera主要完成了两件事:


* **makeclient 创建camera2client对象及Camera3Device对象**
* **初始化camera2client,真正完成打开相机的地方**


    从上述过程看,`Camera2Client`实现的是`Camera API1`的接口,在opencamera时,通过Camera3Device中的BpHwCameraDevice类型对象deviceInfo3->mInterface的open方法完成与HAL3通信来打开相机,并该方法返回结果为ICameraDeviceSession类型对象session,表示相机成功打开,之后所有的相机相关操作全是通过该对象完成。  
 


## 2. startpreview


startPreview时序图如下:  
 ![在这里插入图片描述](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/a85247c56060463cb306d517394dbfc7~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5py65Zmo5a2m5Lmg5LmL5b-DQUk=:q75.awebp?rk3s=f64ab15b&x-expires=1771251427&x-signature=owZl8H1xKom%2Bgci3fTOsxxiYOfk%3D)  
 从上述时序图看,startpreive过程主要有两个过程,


* configureStreams
* 将request插入到mRepeatingRequests队列中,并启动RequestThread,向HAL层不断发送processCaptureRequest申请


## 3. takepicture


开启相机后会启动一个拍照处理线程`mCaptureSequencer`:



template status_t Camera2Client::initializeImpl(TProviderPtr providerPtr) { ATRACE_CALL(); ALOGV("%s: Initializing client for camera %d", FUNCTION, mCameraId); status_t res;

res <span class="token operator">=</span> Camera2ClientBase<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">initialize</span><span class="token punctuation">(</span>providerPtr<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>


#ifdef USE\_QTI\_CAMERA2CLIENT  
 mQTICamera2Client = new QTICamera2Client(this);  
 #endif



mStreamingProcessor = new StreamingProcessor(this); threadName = String8::format("C2-%d-StreamProc", mCameraId);

mFrameProcessor = new FrameProcessor(mDevice, this); threadName = String8::format("C2-%d-FrameProc", mCameraId); mFrameProcessor->run(threadName.string()); //创建拍照处理线程并启动 mCaptureSequencer = new CaptureSequencer(this); threadName = String8::format("C2-%d-CaptureSeq", mCameraId); mCaptureSequencer->run(threadName.string());

mJpegProcessor = new JpegProcessor(this, mCaptureSequencer); threadName = String8::format("C2-%d-JpegProc", mCameraId); mJpegProcessor->run(threadName.string());


#ifdef USE\_QTI\_CAMERA2CLIENT  
 mRawProcessor = new RawProcessor(this, mCaptureSequencer);  
 threadName = String8::format(“C2-%d-RawProc”,  
 mCameraId);  
 mRawProcessor->run(threadName.string());  
 #endif



mZslProcessor = new ZslProcessor(this, mCaptureSequencer);

threadName = String8::format("C2-%d-ZslProc", mCameraId); mZslProcessor->run(threadName.string());

mCallbackProcessor = new CallbackProcessor(this); threadName = String8::format("C2-%d-CallbkProc", mCameraId); mCallbackProcessor->run(threadName.string()); ... return OK;


}  
 


线程中包含有一个状态机,不断检测是否有拍照命令下发,  
 状态机状态定义如下:



enum CaptureState {
    IDLE,
    START,
    ZSL_START,
    ZSL_WAITING,
    ZSL_REPROCESSING,
    STANDARD_START,
    STANDARD_PRECAPTURE_WAIT,
    STANDARD_CAPTURE,
    STANDARD_CAPTURE_WAIT,
    DONE,
    ERROR,
    NUM_CAPTURE_STATES
} mCaptureState;

对应的状态处理函数定义如下:



const CaptureSequencer::StateManager CaptureSequencer::kStateManagers[CaptureSequencer::NUM_CAPTURE_STATES-1] = { &CaptureSequencer::manageIdle, &CaptureSequencer::manageStart, &CaptureSequencer::manageZslStart, &CaptureSequencer::manageZslWaiting, &CaptureSequencer::manageZslReprocessing, &CaptureSequencer::manageStandardStart, &CaptureSequencer::manageStandardPrecaptureWait, &CaptureSequencer::manageStandardCapture, &CaptureSequencer::manageStandardCaptureWait, &CaptureSequencer::manageDone, };


在有拍照命令下发时,状态机进入下一状态START,否则一直停留在IDLE状态



bool CaptureSequencer::threadLoop() {

sp<span class="token operator">&lt;</span>Camera2Client<span class="token operator">&gt;</span> client <span class="token operator">=</span> mClient<span class="token punctuation">.</span><span class="token function">promote</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>client <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token keyword">return</span> false<span class="token punctuation">;</span>

CaptureState currentState<span class="token punctuation">;</span>
<span class="token punctuation">{</span>
    Mutex<span class="token punctuation">:</span><span class="token punctuation">:</span>Autolock <span class="token function">l</span><span class="token punctuation">(</span>mStateMutex<span class="token punctuation">)</span><span class="token punctuation">;</span>
    currentState <span class="token operator">=</span> mCaptureState<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//状态机处理流程</span>
currentState <span class="token operator">=</span> <span class="token punctuation">(</span>this<span class="token operator">-&gt;</span><span class="token operator">*</span>kStateManagers<span class="token punctuation">[</span>currentState<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">(</span>client<span class="token punctuation">)</span><span class="token punctuation">;</span>

Mutex<span class="token punctuation">:</span><span class="token punctuation">:</span>Autolock <span class="token function">l</span><span class="token punctuation">(</span>mStateMutex<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>currentState <span class="token operator">!=</span> mCaptureState<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>mCaptureState <span class="token operator">!=</span> IDLE<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">ATRACE_ASYNC_END</span><span class="token punctuation">(</span>kStateNames<span class="token punctuation">[</span>mCaptureState<span class="token punctuation">]</span><span class="token punctuation">,</span> mStateTransitionCount<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    mCaptureState <span class="token operator">=</span> currentState<span class="token punctuation">;</span>
    mStateTransitionCount<span class="token operator">++</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>mCaptureState <span class="token operator">!=</span> IDLE<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">ATRACE_ASYNC_BEGIN</span><span class="token punctuation">(</span>kStateNames<span class="token punctuation">[</span>mCaptureState<span class="token punctuation">]</span><span class="token punctuation">,</span> mStateTransitionCount<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token function">ALOGV</span><span class="token punctuation">(</span><span class="token string">"Camera %d: New capture state %s"</span><span class="token punctuation">,</span>
            client<span class="token operator">-&gt;</span><span class="token function">getCameraId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> kStateNames<span class="token punctuation">[</span>mCaptureState<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    mStateChanged<span class="token punctuation">.</span><span class="token function">signal</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">if</span> <span class="token punctuation">(</span>mCaptureState <span class="token operator">==</span> ERRORmanageStart<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token function">ALOGE</span><span class="token punctuation">(</span><span class="token string">"Camera %d: Stopping capture sequencer due to error"</span><span class="token punctuation">,</span>
            client<span class="token operator">-&gt;</span><span class="token function">getCameraId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> false<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">return</span> true<span class="token punctuation">;</span>

img img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取