Android Camera HAL3中预览preview模式下的控制流

Camera3研读前沿:

    当初在研读Camera1.0相关的内容时,主要围绕着CameraClient、CameraHardwareInterface等方面进行工作的开展,无论是数据流还是控制流看起来都很简单、明了,一系列的流程化操作使得整个框架学起来特别的容易。因为没有Camera2.0相关的基础,所以这次直接看3.0相关的源码时,显得十分的吃紧,再加上底层高通HAL3.0实现的过程也是相当的复杂,都给整个研读过程带来了很多的困难。可以说,自身目前对Camera3.0框架的熟悉度也大概只有70%左右,希望通过总结来进一步梳理他的工作原理与整个框架,并进一步熟悉与加深理解


1.Camera3下的整体架构图。

整个CameraService建立起一个可用操作底层Camera device大致需要经过Camera2Client、Camera3Device以及HAL层的camera3_device_t三个部分。


从上图中可以发现Camera3架构看上去明显比camera1来的复杂,但他更加的模块化。对比起Android4.2.2 Camer系统架构图(HAL和回调处理)一文中描述的单顺序执行流程,Camera3将更多的工作集中在了Framework去完成,将更多的控制权掌握在自己的手里,从而与HAL的交互的数据信息更少,也进一步减轻了一些在旧版本中HAL层所需要做的事情。


2. Camera2Client的建立与初始化过程


在建立好Camera2Client后会进行initialize操作,完成各个处理模块的创建:

[cpp]  view plain  copy
  1.   ....  
  2. StreamingProcessor = new StreamingProcessor(this);//preview和recorder  
  3.    threadName = String8::format("C2-%d-StreamProc",  
  4.            mCameraId);  
  5.    mStreamingProcessor->run(threadName.string());//预览与录像  
  6.   
  7.    mFrameProcessor = new FrameProcessor(mDevice, this);// 3A  
  8.    threadName = String8::format("C2-%d-FrameProc",  
  9.            mCameraId);  
  10.    mFrameProcessor->run(threadName.string()); //3A  
  11.   
  12.    mCaptureSequencer = new CaptureSequencer(this);  
  13.    threadName = String8::format("C2-%d-CaptureSeq",  
  14.            mCameraId);  
  15.    mCaptureSequencer->run(threadName.string());//录像,拍照  
  16.   
  17.    mJpegProcessor = new JpegProcessor(this, mCaptureSequencer);  
  18.    threadName = String8::format("C2-%d-JpegProc",  
  19.            mCameraId);  
  20.    mJpegProcessor->run(threadName.string());  
  21. ...  
  22. mCallbackProcessor = new CallbackProcessor(this);//回调处理  
  23.    threadName = String8::format("C2-%d-CallbkProc",  
  24.            mCameraId);  
  25.    mCallbackProcessor->run(threadName.string());  
依次分别创建了:

StreamingProcessor并启动一个他所属的thread,该模块主要负责处理previews与record两种视频流的处理,用于从hal层获取原始的视频数据

FrameProcessor并启动一个thread,该模块专门用于处理回调回来的每一帧的3A等信息,即每一帧视频除去原始视频数据外,还应该有其他附加的数据信息,如3A值。

CaptureSequencer并启动一个thread,该模块需要和其他模块配合使用,主要用于向APP层告知capture到的picture。
JpegProcessor并启动一个thread,该模块和streamprocessor类似,他启动一个拍照流,一般用于从HAL层获取jpeg编码后的图像照片数据。

此外ZslProcessor模块称之为0秒快拍,其本质是直接从原始的Preview流中获取预存着的最近的几帧,直接编码后返回给APP,而不需要再经过take picture去请求获取jpeg数据。0秒快拍技术得意于当下处理器CSI2 MIPI性能的提升以及Sensor支持全像素高帧率的实时输出。一般手机拍照在按下快门后都会有一定的延时,是因为需要切换底层Camera以及ISP等的工作模式,并重新设置参数以及重新对焦等等,都需要花一定时间后才抓取一帧用于编码为jpeg图像。

以上5个模块整合在一起基本上实现了Camera应用开发所需的基本业务功能。


3. 预览Preview下的控制流

研读Camera具体的业务处理功能,一般从视频实时预览Preview入手。一般熟悉Camera架构的人,可以从一个app端的一个api一直连续打通到底层hal的一个控制命令。大致可以如下图所示:


对于preview部分到CameraService的控制流可以参考博文Android4.2.2的preview的数据流和控制流以及最终的预览显示,本文将直接从Camera2Client::startPreview() 作为入口来分析整个Framework层中Preview相关的数据流。

[cpp]  view plain  copy
  1. status_t Camera2Client::startPreview() {  
  2.     ATRACE_CALL();  
  3.     ALOGV("%s: E", __FUNCTION__);  
  4.     Mutex::Autolock icl(mBinderSerializationLock);  
  5.     status_t res;  
  6.     if ( (res = checkPid(__FUNCTION__) ) != OK) return res;  
  7.     SharedParameters::Lock l(mParameters);  
  8.     return startPreviewL(l.mParameters, false);  
  9. }  
startPreview通过startPreviewL提取参数后真正的开始执行Preview相关的控制流。该函数看上去内容虽然较多,但基本采用了同一种处理方式:
[cpp]  view plain  copy
  1. status_t Camera2Client::startPreviewL(Parameters ¶ms, bool restart) {//restart == false  
  2.     ATRACE_CALL();  
  3.     status_t res;  
  4. ......  
  5.    int lastPreviewStreamId = mStreamingProcessor->getPreviewStreamId();//获取上一层Preview stream id  
  6.   
  7.    res = mStreamingProcessor->updatePreviewStream(params);//创建camera3device stream, Camera3OutputStream  
  8. .....  
  9.    int lastJpegStreamId = mJpegProcessor->getStreamId();  
  10.    res = updateProcessorStream(mJpegProcessor, params);//预览启动时就建立一个jpeg的outstream  
  11. .....  
  12.         res = mCallbackProcessor->updateStream(params);//回调处理建立一个Camera3outputstream  
  13.         if (res != OK) {  
  14.             ALOGE("%s: Camera %d: Unable to update callback stream: %s (%d)",  
  15.                     __FUNCTION__, mCameraId, strerror(-res), res);  
  16.             return res;  
  17.         }  
  18.         outputStreams.push(getCallbackStreamId());  
  19. ......  
  20.     outputStreams.push(getPreviewStreamId());//预览stream  
  21. ......  
  22.    if (!params.recordingHint) {  
  23.         if (!restart) {  
  24.             res = mStreamingProcessor->updatePreviewRequest(params);//request处理,更新了mPreviewrequest  
  25.             if (res != OK) {  
  26.                 ALOGE("%s: Camera %d: Can't set up preview request: "  
  27.                         "%s (%d)", __FUNCTION__, mCameraId,  
  28.                         strerror(-res), res);  
  29.                 return res;  
  30.             }  
  31.         }  
  32.         res = mStreamingProcessor->startStream(StreamingProcessor::PREVIEW,  
  33.                 outputStreams);//启动stream,传入outputStreams即stream 的id  
  34.     } else {  
  35.         if (!restart) {  
  36.             res = mStreamingProcessor->updateRecordingRequest(params);  
  37.             if (res != OK) {  
  38.                 ALOGE("%s: Camera %d: Can't set up preview request with "  
  39.                         "record hint: %s (%d)", __FUNCTION__, mCameraId,  
  40.                         strerror(-res), res);  
  41.                 return res;  
  42.             }  
  43.         }  
  44.         res = mStreamingProcessor->startStream(StreamingProcessor::RECORD,  
  45.                 outputStreams);  
  46.     }  
  47. ......  
  48. }  


(1). mStreamingProcessor->updatePreviewStream()

由预览与录像处理模块更新一个预览流,其实现过程如下:

[cpp]  view plain  copy
  1. status_t StreamingProcessor::updatePreviewStream(const Parameters ¶ms) {  
  2.     ATRACE_CALL();  
  3.     Mutex::Autolock m(mMutex);  
  4.   
  5.     status_t res;  
  6.     sp<CameraDeviceBase> device = mDevice.promote();//Camera3Device  
  7.     if (device == 0) {  
  8.         ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);  
  9.         return INVALID_OPERATION;  
  10.     }  
  11.   
  12.     if (mPreviewStreamId != NO_STREAM) {  
  13.         // Check if stream parameters have to change  
  14.         uint32_t currentWidth, currentHeight;  
  15.         res = device->getStreamInfo(mPreviewStreamId,  
  16.                 ¤tWidth, ¤tHeight, 0);  
  17.         if (res != OK) {  
  18.             ALOGE("%s: Camera %d: Error querying preview stream info: %2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值