Android Camera HAL3中拍照Capture模式下多模块间的交互与帧Result与帧数据回调_第1页
Android Camera HAL3中拍照Capture模式下多模块间的交互与帧Result与帧数据回调_第2页
Android Camera HAL3中拍照Capture模式下多模块间的交互与帧Result与帧数据回调_第3页
Android Camera HAL3中拍照Capture模式下多模块间的交互与帧Result与帧数据回调_第4页
Android Camera HAL3中拍照Capture模式下多模块间的交互与帧Result与帧数据回调_第5页
已阅读5页,还剩24页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Android Camera HAL3中拍照Capture模式下多模块间的交互与帧Result与帧数据回调本文均属自己阅读源码的点滴总结,转账请注明出处谢谢。欢迎和大家交流。qq:1037701636 email:gzzaigcn2009Software:系统源码Android5.1前沿:    之前的两篇博文算是比较详细的记录了整个Camera3 HAL3架构下完全不同于HAL1的preview预览处理过程,包括主要涉及到的控制流和视频流等。比较详细的阐述了Camera2Client下streamProcessor、CallbackProcessor、CaptureSeq

2、uencer等模块在Camera3架构下的功能。分析得出每个模块下均会在Camera3Device下以一个Stream的形式存在,而每个stream又是由多个buffer来构成主体的。与HAL3进行数据的交互时,以Request和result来作为数据传输的载体。在这些基础上本文将描述具体拍照Capture模式下的数据流和控制流,主要会涉及到jpegprocessor、CaptureSequencer这几个模块的工作原理。鉴于Capture模式下的数据流更复杂,在这里重点会分析数据流result回传时,每个模块的响应以及处理过程,填补前一博文的空白。1. HAL3中Camera2Client下

3、的take picture的入口函数作为标准的capture picture功能的入口,主要完成了以下两件事情:updateProcessorStream(mJpegProcessor, l.mParameters);mCaptureSequencer->startCapture(msgType)    对于JpegProcessor模块而言,他的stream流第一次是在preview阶段进行了create与初始化,这里之所以再次调用JpegProcessor:updateStream目的是参考原先JpegProcessor stream的width与hei

4、ght是否变化即是否照片要求的分辨率发生了变化,如果是的话就需要delete原先的stream,重新建立一个stream。    在JpegProcessor中重点关注CpuConsumer与Surface的生产者与消费者处理模式,官方称之为Create CPU buffer queue endpoint。2. CaptureSequencer模块    CaptureSequencer模块是take picture下操作的重点,在Camera2Client中进行了创建,首先来看CaptureSequencer线程的threadLoop函数:c

5、pp view plaincopy1. bool CaptureSequencer:threadLoop()   2.   3.     sp<Camera2Client> client = mCmote();  4.     if (client = 0) return false;  5. &#

6、160; 6.     CaptureState currentState;  7.       8.         Mutex:Autolock l(mStateMutex);  9.         currentState = mCaptur

7、eState;  10.       11.   12.     currentState = (this->*kStateManagerscurrentState)(client);  13.   14.     Mutex:Autolock l(mStateMutex);  15.    

8、 if (currentState != mCaptureState)   16.         if (mCaptureState != IDLE)   17.             ATRACE_ASYNC_END(kStateNamesmCaptureStat

9、e, mStateTransitionCount);  18.           19.         mCaptureState = currentState;/保留新的状态  20.         mStateTransitionCount+; &#

10、160;21.         if (mCaptureState != IDLE)   22.             ATRACE_ASYNC_BEGIN(kStateNamesmCaptureState, mStateTransitionCount);  23.    &#

11、160;      24.         ALOGV("Camera %d: New capture state %s",  25.                 client->getCameraI

12、d(), kStateNamesmCaptureState);  26.         mStateChanged.signal();  27.       28.   29.     if (mCaptureState = ERROR)   30.    

13、     ALOGE("Camera %d: Stopping capture sequencer due to error",  31.                 client->getCameraId();  32.   &

14、#160;     return false;  33.       34.   35.     return true;  36.   CaptureSequencer是一个以不同的state状态机来循环工作的模块, currentState = (this->*kStateManagerscurrentState)(client

15、)函数是执行对应状态机下的执行函数,其中的state值如下:cpp view plaincopy1. const CaptureSequencer:StateManager  2.         CaptureSequencer:kStateManagersCaptureSequencer:NUM_CAPTURE_STATES-1 =   3.     &CaptureSequencer

16、:manageIdle,  4.     &CaptureSequencer:manageStart,  5.     &CaptureSequencer:manageZslStart,  6.     &CaptureSequencer:manageZslWaiting,  7.     &CaptureSequencer:

17、manageZslReprocessing,  8.     &CaptureSequencer:manageStandardStart,  9.     &CaptureSequencer:manageStandardPrecaptureWait,  10.     &CaptureSequencer:manageStandardCapture,  11.  &

18、#160;  &CaptureSequencer:manageStandardCaptureWait,  12.     &CaptureSequencer:manageBurstCaptureStart,  13.     &CaptureSequencer:manageBurstCaptureWait,  14.     &CaptureSequencer:ma

19、nageDone,  15. ;  我们以一个standard capture的操作模式,来分析一次完成的take picture的过程。初始化的 mCaptureState(IDLE),进入的函数入口为manageIdle:cpp view plaincopy1. CaptureSequencer:CaptureState CaptureSequencer:manageIdle(  2.         sp<Came

20、ra2Client> &/*client*/)   3.     status_t res;  4.     Mutex:Autolock l(mInputMutex);  5.     while (!mStartCapture)   6.        

21、; res = mStartCaptureSignal.waitRelative(mInputMutex,  7.                 kWaitDuration);  8.         if (res = TIMED_OUT) br

22、eak;  9.       10.     if (mStartCapture)   11.         mStartCapture = false;  12.         mBusy = true; 

23、; 13.         return START;  14.       15.     return IDLE;  16.   函数主要在轮训mStartCapture的值,这个值是由CameraService端的拍照触发线程来启动的,代码如下:cpp view plaincopy1. status_t 

24、;CaptureSequencer:startCapture(int msgType)   2.     ALOGV("%s", _FUNCTION_);  3.     ATRACE_CALL();  4.     Mutex:Autolock l(mInputMutex);  5.     if

25、 (mBusy)   6.         ALOGE("%s: Already busy capturing!", _FUNCTION_);  7.         return INVALID_OPERATION;  8.      &

26、#160;9.     if (!mStartCapture)   10.         mMsgType = msgType;  11.         mStartCapture = true;  12.      

27、0;  mStartCaptureSignal.signal();/启动CaptureSequencer  13.       14.     return OK;  15.   对比CaptureSequencer Threadloop线程中,在阻塞式的等待mStartCapture = true,并在修改完mStartCapture 后向Threadloop发出signal。Threadloo

28、p线程被唤醒后,执行返回一个新的状态机mCaptureState = START:2.1 START状态机主要调用了updateCaptureRequest(l.mParameters, client)函数:cpp view plaincopy1. status_t CaptureSequencer:updateCaptureRequest(const Parameters ¶ms,  2.         sp<Camera2C

29、lient> &client)   3.     ATRACE_CALL();  4.     status_t res;  5.     if (mCaptureRequest.entryCount() = 0)   6.        

30、60;res = client->getCameraDevice()->createDefaultRequest(  7.                 CAMERA2_TEMPLATE_STILL_CAPTURE,  8.            

31、0;    &mCaptureRequest);  9.         if (res != OK)   10.             ALOGE("%s: Camera %d: Unable to crea

32、te default still image request:"  11.                     " %s (%d)", _FUNCTION_, client->getCameraId(),  12.   

33、                  strerror(-res), res);  13.             return res;  14.        

34、0;  15.       16.   17.     res = params.updateRequest(&mCaptureRequest);  18.     if (res != OK)   19.         ALOG

35、E("%s: Camera %d: Unable to update common entries of capture "  20.                 "request: %s (%d)", _FUNCTION_, clie

36、nt->getCameraId(),  21.                 strerror(-res), res);  22.         return res;  23.       24.  

37、; 25.     res = params.updateRequestJpeg(&mCaptureRequest);/更新JPEG需要的参数  26.     if (res != OK)   27.         ALOGE("%s: Camera %d: Unable

38、60;to update JPEG entries of capture "  28.                 "request: %s (%d)", _FUNCTION_, client->getCameraId(),  29.   

39、              strerror(-res), res);  30.         return res;  31.       32.   33.     return OK

40、;  34.        该函数和preview模式下的updatePreviewRequest很类似,这里首先检查mCaptureRequest是否是一个空的CameraMetadata,如果为空则由createDefaultRequest来请求HAL3来创建一个Request,其中相应的类型为CAMERA2_TEMPLATE_STILL_CAPTURE。随后分别是使用当前模式下的配置参数来更新CameraMetadata mCaptureRequest中不同tag的参数值,便于传递给HAL3,这个过程是类似与

41、以前Camera1中直接的setParamters操作string的过程。2.2 STANDARD_START状态manageStandardCapture该状态是启动整个take picture的重点所在:cpp view plaincopy1. CaptureSequencer:CaptureState CaptureSequencer:manageStandardCapture(  2.         sp<Camera2Client> 

42、;&client)   3.     status_t res;  4.     ATRACE_CALL();  5.     SharedParameters:Lock l(client->getParameters();  6.     Vector<int32_t> outputStre

43、ams;  7.     uint8_t captureIntent = static_cast<uint8_t>(ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE);  8.   9.     /* 10.      * Set up output streams 

44、in the request 11.      *  - preview 12.      *  - capture/jpeg 13.      *  - callback (if preview callbacks enabled) 14.  &#

45、160;   *  - recording (if recording enabled) 15.      */  16.     outputStreams.push(client->getPreviewStreamId();/preview Stream  17.     outputStreams.push

46、(client->getCaptureStreamId();/capture Stream  18.   19.     if (l.mParameters.previewCallbackFlags &  20.             CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) 

47、0; 21.         outputStreams.push(client->getCallbackStreamId();/capture callback  22.       23.   24.     if (l.mParameters.state = Parameters:VIDEO_SNAPSHOT)

48、60;  25.         outputStreams.push(client->getRecordingStreamId();  26.         captureIntent = static_cast<uint8_t>(ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT);  27.

49、      28.   29.     res = mCaptureRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS,  30.             outputStreams);  31.     if 

50、;(res = OK)   32.         res = mCaptureRequest.update(ANDROID_REQUEST_ID,  33.                 &mCaptureId, 1);/当前request对应的I

51、D  34.       35.     if (res = OK)   36.         res = mCaptureRequest.update(ANDROID_CONTROL_CAPTURE_INTENT,  37.       

52、;          &captureIntent, 1);  38.       39.     if (res = OK)   40.         res = mCaptureRequest.s

53、ort();  41.       42.   43.     if (res != OK)   44.         ALOGE("%s: Camera %d: Unable to set up still capture&#

54、160;request: %s (%d)",  45.                 _FUNCTION_, client->getCameraId(), strerror(-res), res);  46.         return D

55、ONE;  47.       48.   49.     / Create a capture copy since CameraDeviceBase#capture takes ownership  50.     CameraMetadata captureCopy = mCaptu

56、reRequest;  51.     if (captureCopy.entryCount() = 0)   52.         ALOGE("%s: Camera %d: Unable to copy capture request for HAL device",

57、60; 53.                 _FUNCTION_, client->getCameraId();  54.         return DONE;  55.       56.   

58、57.     /* 58.      * Clear the streaming request for still-capture pictures 59.      *   (as opposed to i.e. video snapshots) 60.  

59、60;   */  61.     if (l.mParameters.state = Parameters:STILL_CAPTURE)   62.         / API definition of takePicture() - stop preview before 

60、taking pic  63.         res = client->stopStream();  64.         if (res != OK)   65.            

61、 ALOGE("%s: Camera %d: Unable to stop preview for still capture: "  66.                     "%s (%d)", &#

62、160;67.                     _FUNCTION_, client->getCameraId(), strerror(-res), res);  68.             return

63、0;DONE;  69.           70.       71.     / TODO: Capture should be atomic with setStreamingRequest here  72.     res

64、0;= client->getCameraDevice()->capture(captureCopy);/启动camera3device的capture,提交capture request  73.     if (res != OK)   74.         ALOGE("%s: Camera %d: Unable

65、60;to submit still image capture request: "  75.                 "%s (%d)",  76.            

66、60;    _FUNCTION_, client->getCameraId(), strerror(-res), res);  77.         return DONE;  78.       79.   80.     mTimeoutCount =&#

67、160;kMaxTimeoutsForCaptureEnd;  81.     return STANDARD_CAPTURE_WAIT;  82.   83.   84. CaptureSequencer:CaptureState CaptureSequencer:manageStandardCaptureWait(  85.         sp<

68、Camera2Client> &client)   86.     status_t res;  87.     ATRACE_CALL();  88.     Mutex:Autolock l(mInputMutex);  89.   90.     / Wait 

69、;for new metadata result (mNewFrame)  91.     while (!mNewFrameReceived)   92.         res = mNewFrameSignal.waitRelative(mInputMutex, kWaitDuration);/wait new 一帧met

70、adata  93.         if (res = TIMED_OUT)   94.             mTimeoutCount-;  95.             

71、;break;  96.           97.       98.   99.     / Approximation of the shutter being closed  100.     / - TODO:

72、 use the hal3 exposure callback in Camera3Device instead  101.     if (mNewFrameReceived && !mShutterNotified)   102.         SharedParameters:Lock 

73、;l(client->getParameters();  103.         /* warning: this also locks a SharedCameraCallbacks */  104.         shutterNotifyLocked(l.mParameters, client,

74、0;mMsgType);  105.         mShutterNotified = true;  106.       107.   108.     / Wait until jpeg was captured by JpegProcessor &#

75、160;109.     while (mNewFrameReceived && !mNewCaptureReceived)   110.         res = mNewCaptureSignal.waitRelative(mInputMutex, kWaitDuration);/等待JPEG数据  111.    

76、     if (res = TIMED_OUT)   112.             mTimeoutCount-;  113.             break;  114.   &

77、#160;       115.       116.     if (mTimeoutCount <= 0)   117.         ALOGW("Timed out waiting for capture to&#

78、160;complete");  118.         return DONE;  119.       120.     if (mNewFrameReceived && mNewCaptureReceived) /满足mNewFrameReceived  121.  

79、;       if (mNewFrameId != mCaptureId)   122.             ALOGW("Mismatched capture frame IDs: Expected %d, got %d",  12

80、3.                     mCaptureId, mNewFrameId);  124.           125.         camera_metadata_e

81、ntry_t entry;  126.         entry = mNewFrame.find(ANDROID_SENSOR_TIMESTAMP);  127.         if (entry.count = 0)   128.       

82、;      ALOGE("No timestamp field in capture frame!");  129.          else if (entry.count = 1)   130.        &

83、#160;    if (entry.data.i640 != mCaptureTimestamp)   131.                 ALOGW("Mismatched capture timestamps: Metadata frame %" 

84、PRId64 ","  132.                         " captured buffer %" PRId64,  133.       

85、60;                 entry.data.i640,  134.                         mCaptureTimestamp)

86、;  135.               136.          else   137.             ALOGE("Timestamp metadata 

87、;is malformed!");  138.           139.         client->removeFrameListener(mCaptureId, mCaptureId + 1, this);  140.   141.     

88、    mNewFrameReceived = false;  142.         mNewCaptureReceived = false;  143.         return DONE;  144.       14

89、5.     return STANDARD_CAPTURE_WAIT;  146.   整个函数的处理可以分为以下几个小点:a:Vector<int32_t> outputStreams; outputStreams.push(client->getPreviewStreamId();/preview Stream outputStreams.push(client->getCaptureStreamId();/capture jpeg Streamoutpu

90、tStreams.push(client->getCallbackStreamId();/capture callback通过以上的操作,可以很清楚是看到,这里集合了take picture所需要使用到的stream流,对应的模块分别是:streamProcessor、jpegProcessor、CallbackProcessor。这个过程和Preview模式下是类似的,收集当前Camera2Client下的所有stream,并以stream的ID号作为区别。b: 将当前操作所有的stream信息全部加入到CameraMetadata mCaptureRequest 

91、   res = mCaptureRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS,            outputStreams);    if (res = OK)         res = mCaptureRequest.update(ANDROID_REQUEST_ID,                &mCaptureId

92、, 1);/当前request对应的ID    ANDROID_REQUEST_ID这项值表明,当前只存在3种Request类型:cpp view plaincopy1. 预览Request mPreviewRequest:        mPreviewRequestId(Camera2Client:kPreviewRequestIdStart),  2. 拍照Request mCaptureRequest:mCaptureId(Camera2

93、Client:kCaptureRequestIdStart),  3. 录像Request mRecordingRequest:        mRecordingRequestId(Camera2Client:kRecordingRequestIdStart),  c. 对于STILL_CAPTURE类型的pictureclient->stopStream(),实现的本质是res = device->clearStreamingRequest(),mR

94、equestThread->clearRepeatingRequests(lastFrameNumber);该函数是将之前Preview模式下的建立的captureRequest作delete处理,之前在预览模式下是将最终生产的capturelist加入到了一个mRepeatingRequests当中,这里通过clear使之为empty,即不会再发送Request和HAL3进行数据的交互。d.Camera3Device capture函数首先关注capture函数传入的参数为captureCopy,即CameraMetadata mCaptureRequest的一个copy值。

95、cpp view plaincopy1. status_t Camera3Device:capture(CameraMetadata &request, int64_t* /*lastFrameNumber*/)   2.     ATRACE_CALL();  3.   4.     List<const CameraMetadata> requests;

96、  5.     requests.push_back(request);/对于一个CameraMetadata转为list  6.     return captureList(requests, /*lastFrameNumber*/NULL);  7.   cpp view plaincopy1. status_t Camera3Device:captureList(const L

97、ist<const CameraMetadata> &requests,  2.                                     int64_t 

98、*lastFrameNumber)   3.     ATRACE_CALL();  4.   5.     return submitRequestsHelper(requests, /*repeating*/false, lastFrameNumber);/非重复的,制定于拍照  6.   capture函数由Camera3Device来响应处理,其传入的mCaptureR

99、equest转变为一个list,再交由submitRequestsHelper来处理,对比之前Preview下的处理方式,其startstream入口为setStreamingRequest->setStreamingRequestList->submitRequestsHelper。这也表明了最终CameraMetadata类型的Request都是由submitRequestsHelper来完成的,所以convertMetadataListToRequestListLocked这个将CameraMetadata转换为List<sp<CaptureRequest>

100、 > RequestList的处理过程对两者来说都是一致的。但在后续处理时,对picture模式下的Request,其不再是repeating的处理,mRequestThread->queueRequestList():cpp view plaincopy1. status_t Camera3Device:RequestThread:queueRequestList(  2.         List<sp<CaptureRequest>

101、0;> &requests,  3.         /*out*/  4.         int64_t *lastFrameNumber)   5.     Mutex:Autolock l(mRequestLock);  6.   

102、60; for (List<sp<CaptureRequest> >:iterator it = requests.begin(); it != requests.end();  7.             +it)   8.        &

103、#160;mRequestQueue.push_back(*it);  9.     .  10.     unpauseForNewRequests();  11.   12.     return OK;  13.   这里直接是将CaptureRequest加入到RequestQueue这个队列之中,区别于Preview模式是将capture

104、Request加入到一个mRepeatingRequests,重复的将其中的captureRequest加入到RequestQueue。最简单的理解是picture模式下是拍去几帧的数据流即可,Preview模式下是实时的获取帧,前者是几次one snop,后者是连续continuous。到这里为止,可以说CaptureSequence已经完成了START状态机的处理。e. 从START到STANDARD_CAPTURE_WAIT该状态下对应的状态机处理函数为manageStandardCaptureWait:cpp view plaincopy1. CaptureSequencer

105、:CaptureState CaptureSequencer:manageStandardCaptureWait(  2.         sp<Camera2Client> &client)   3.     status_t res;  4.     ATRACE_CALL();  5. 

106、60;   Mutex:Autolock l(mInputMutex);  6.   7.     / Wait for new metadata result (mNewFrame)  8.     while (!mNewFrameReceived)   9.     

107、60;   res = mNewFrameSignal.waitRelative(mInputMutex, kWaitDuration);/wait new 一帧metadata  10.         if (res = TIMED_OUT)   11.         &#

108、160;   mTimeoutCount-;  12.             break;  13.           14.       15.   16.     / Ap

109、proximation of the shutter being closed  17.     / - TODO: use the hal3 exposure callback in Camera3Device instead  18.     if (mNewFrameReceived &&

110、; !mShutterNotified)   19.         SharedParameters:Lock l(client->getParameters();  20.         /* warning: this also locks a SharedCameraCallbacks

111、0;*/  21.         shutterNotifyLocked(l.mParameters, client, mMsgType);  22.         mShutterNotified = true;  23.       24.   25.

112、     / Wait until jpeg was captured by JpegProcessor  26.     while (mNewFrameReceived && !mNewCaptureReceived)   27.         res =&

113、#160;mNewCaptureSignal.waitRelative(mInputMutex, kWaitDuration);/等待JPEG数据  28.         if (res = TIMED_OUT)   29.             mTimeoutCount-;  30

114、.             break;  31.           32.       33.     if (mTimeoutCount <= 0)   34.   &

115、#160;     ALOGW("Timed out waiting for capture to complete");  35.         return DONE;  36.       37.     if (mNew

116、FrameReceived && mNewCaptureReceived) /满足mNewFrameReceived  38.         if (mNewFrameId != mCaptureId)   39.             ALOGW("Mismatched capture frame IDs: 

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论