前言
前面说过上层把Request送到Hal层之后,Hal层会将处理结果通过processCaptureResult()这个回调接口返回给上层。processCaptureResult这个接口其实是在ICameraDeviceCallback这个类当中定义的,在openCamera这一节有提及过,在openSession()时,有将ICameraDeviceCallback这个Class传给Hal,更具体地说是Camera3Device,因为Camera3Device有从ICameraDeviceCallback继承,是它的子类。所以其实底层是调用了Camera3Device::processCaptureResult()
接下来就从Hal调用processCaptureResult()开始讲起,关于这个接口,google在hardware\interfaces\camera\device\有比较详细的说明,该函数会将metadata返回给app,以及将output buffer和input buffer返回给stream,processCaptureResult()中所带的参数是一个CaptureResult类型的数组。
hardware::Return<void> Camera3Device::processCaptureResult(
const hardware::hidl_vec<hardware::camera::device::V3_2::CaptureResult>& results)
这个CaptureResult的数据结构是下面这样子,其是里面就是Metadata、Buffer、frameNumber这些资讯:
下面是processCaptureResult()的流程图,后面来简单地说明一下其中涉及到的一些函数。
一、processOneCaptuResultLocked()
对每一个Result调用一次这个接口,这个函数里主要读取CaptureResult里的资讯,为camera_capture_result这个结构体的成员赋值,camera_capture_result其结构体如下:
1、readOneCameraMetadataLocked()
从mResultMetadataQueue或者CaptureResult里读取Metadata
2、bufferRecords.popInflightBuffer()
先获取这次result中返回的outbuffer,有返回多少块Buffer,就调用多少次popInflightBuffer(),这里面做的事情是:先从mInflightBufferMap里根据framenumber和streamId取出对应的Buffer,并将其mInflightBufferMap的记录里中移除,这个mInflightBufferMap代表当前Hal层正在使用的Buffer,如果底层有处理完后还回来,当然就该移除掉了。
3. processCaptureResult()
- SendPartialCaptureResult
一个Request可能会分为多个子集回上去,在openCamera时,在camera3Device::initializeCommonLocked()时,会根据ANDROID_REQUEST_PARTIAL_RESULT_COUNT决定这个request会分几包(即partial result)返回。如果是partialResult,并且Request hasCallBack则会调用到这里,hasCallBack通常为true,除了在Constrained High Speed 下,必须要是这个batch的最后一个Request才可以ture,这一步其实就是把CaptureResult push进mResultQueue的队尾
- returnAndRemovePendingOutputBuffers()
这一步是很重要的起步,由上面的时序图,可以发现它的作用就是将Hal层返回回来的buffer queue进对应的BufferQueue里,以让Consumer来取用。
- SendCaptureResult()
和SendPartialCaptureResult作用差不多,主要是把captureRequest push进mResultQueue的队尾,当然这一步是和前面SendPartialCaptureResult是互斥的,这里只有request相关的最后包meta回来时,会走到这里。
- removeInFlightRequestIfReadyLocked
如果这个Request已经处理完毕,即所有的Buffer和Metadata有全部正确返回,那么就将这个Request从mInFlightMap里移除掉,表示这个Request已经全部返回。
二、FrameProcessorBase
讲到现在,metadata是放在了mResultQueue里,在前面openCamera这一节有讲过,在初始化CameraDeviceClient时,有创建了一个名叫FrameProcessor的线程,那么这个线程是在做什么事情呢?它的主要作用就是前面放进了mResultQueue里的Metadata callback给App,它的流程图如下:
总结起来就是,waitForNextFrame()里检测到mResultQueue不为空之后,然后通过getNextResult()从mResultQueue里面将队头的Metadata取出来;然后通过回调函数,将meta返回回去,最后送到CameraDevice时,会根据这包meta是partial meta还是最后一包meta调用不同的回调函数,如果是partial meta,会调用onCaptureProgressed()返回给CaptureSession(图中红框部分),如果是最后一包meta,则会调用onCaptureCompleted()返回给CaptureSession(图中绿框部分)。这个回调函数是前面CaptureSession里下Request时带下去的。