57. (*item)->onResultAvailable(result);//所有注册的listener,告知有result返回 58. } 59. return OK; 60. } 这里简单的理解是在获取一个正常的CaptureResult时,就需要将这个Result分发给哪些感兴趣的模块,而这个过程由一个FilteredListener来完成:
其他模块如果想要listen FrameProcessor模块,可以调用registerListener来注册,保存在mRangeListeners之中,具体的接口如下: [cpp] view plaincopy
1. status_t Camera2Client::registerFrameListener(int32_t minId, int32_t maxId, 2. wp
其中CaptureSequencer::manageStandardStart()在处理时,调用了registerFrameListener完成了listen的注册。
有了这些listener,在processListeners处理函数中,通过遍历
mRangeListeners,来确保当前的CaptureResult 中对象的Request id和注册时的区间相匹配。在提取到适合处理当前Result的listener后,回调onResultAvailable()函数。
到这里void CaptureSequencer::onResultAvailable()就会被覆盖调用,经而我们定位到了mNewFrameReceived = Ture的回调过程。
3.4. 帧数据的回调:
上面重点是分析一个队CameraMetadata Result结果的分析,看上去还没有真正的视频帧数据的出现。对于视频流buffer的操作,上面提到了肯定是需要stream的,而不像FrameProcessor不需要建立stream来进行数据的传输。
对于数据的Callback处理,接口是returnOutputBuffers函数,该函数在preview模式下已经进行过分析,其重点就是将当前Result回来的buffer数据信息进行提取,然后分发给不同模块所维护着的Camera3Stream去作处理,本质是将当前
26
Result返回的camera3_stream_buffer提取buffer_handle后通过queue_buffer操作后,就交由对应的Consumer去作处理。
对于直接预览的模块StreamProcessor,其Consumer是直接的SurfaceFlinger用于实时显示,CallbackProcessor是将CpuConsumer来将帧数据回传给APP使用,这些过程和Preview模式下都是类似,也是takepicture模式下同样需要处理的过程,而对于JpegProcessor而言,属于Picture模式专属,我们来看他接收到一帧HAL3 Jpeg Buffer的处理过程: [cpp] view plaincopy
1. void JpegProcessor::onFrameAvailable(const BufferItem& /*item*/) { 2. Mutex::Autolock l(mInputMutex); 3. if (!mCaptureAvailable) { 4. mCaptureAvailable = true; 5. mCaptureAvailableSignal.signal();//采集到一帧jpeg图像 6. } 7. } 上述调用的过程可参看博文Android5.1中surface和CpuConsumer下生产者和消费者间的处理框架简述来加深理解,作为take picture模式下独有的模块,对应的Threadloop线程获得响应: [cpp] view plaincopy
1. bool JpegProcessor::threadLoop() { 2. status_t res; 3. 4. { 5. Mutex::Autolock l(mInputMutex); 6. while (!mCaptureAvailable) { 7. res = mCaptureAvailableSignal.waitRelative(mInputMutex, 8. kWaitDuration); 9. if (res == TIMED_OUT) return true; 10. } 11. mCaptureAvailable = false; 12. } 13. 14. do { 15. res = processNewCapture();//处理新的jpeg采集帧 16. } while (res == OK); 17. 27
18. 19. return true; } 调用processNewCapture(),函数内部主要包括以下几个方面:
mCaptureConsumer->lockNextBuffer(&imgBuffer);这是从CPUConsumer中获取一个已经queuebuffer的buffer,lock过程最重要的是将这个buffer作mmap操作后映射到当前线程中。
然后通过这个虚拟地址将buffer地址copy到本进程的一个heap中,随后将这个buffer进行ummap操作。
最后是调用如下代码,去将本地的jpegbuffer传输给CaptureSequencer,所以可以说CaptureSequence虽然负责收集jpeg等数据,负责整个take picture的启动与控制,但本质上jpeg等数据的真正提取都是交由jpegprocessor、zslprocessor等模块来完成:
[cpp] view plaincopy
1. sp
至此为止onResultAvailable()与onCaptureAvailable()均完成了回调,前者主要是由FrameProcessor来触发的,后者是有jpegProcessor来触发的,前者是回传的一帧jpeg图像的附加信息如timestamp/3A等,而后者是回传了一帧真正的jpeg图像。
下面是我小节的takepicture模式下几个模块间数据交互的过程图,本质是几个线程间Threadloop的响应与处理过程。
可以看到jpeg模式下,每次课回传给APP的数据包括原始的Callback数据流,jpegprocessor中的jpeg图像流,以及其他比如AF的状态,人脸识别后的人脸坐标原始信息camera_frame_metadata_t回传给APP。
28
29
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库Android Camera HAL3中拍照Capture模式下多模块间的交互与帧Resu(6)在线全文阅读。
相关推荐: