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操作,完成各個處理模塊的創建:

  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相關的數據流。

  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相關的控制流。該函數看上去內容雖然較多,但基本採用了同一種處理方式:
  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()

由預覽與錄像處理模塊更新一個預覽流,其實現過程如下:

  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: "  
  19.                     "%s (%d)", __FUNCTION__, mId, strerror(-res), res);  
  20.             return res;  
  21.         }  
  22.         if (currentWidth != (uint32_t)params.previewWidth ||  
  23.                 currentHeight != (uint32_t)params.previewHeight) {  
  24.             ALOGV("%s: Camera %d: Preview size switch: %d x %d -> %d x %d",  
  25.                     __FUNCTION__, mId, currentWidth, currentHeight,  
  26.                     params.previewWidth, params.previewHeight);  
  27.             res = device->waitUntilDrained();  
  28.             if (res != OK) {  
  29.                 ALOGE("%s: Camera %d: Error waiting for preview to drain: "  
  30.                         "%s (%d)", __FUNCTION__, mId, strerror(-res), res);  
  31.                 return res;  
  32.             }  
  33.             res = device->deleteStream(mPreviewStreamId);  
  34.             if (res != OK) {  
  35.                 ALOGE("%s: Camera %d: Unable to delete old output stream "  
  36.                         "for preview: %s (%d)", __FUNCTION__, mId,  
  37.                         strerror(-res), res);  
  38.                 return res;  
  39.             }  
  40.             mPreviewStreamId = NO_STREAM;  
  41.         }  
  42.     }  
  43.   
  44.     if (mPreviewStreamId == NO_STREAM) {//首次create stream  
  45.         res = device->createStream(mPreviewWindow,  
  46.                 params.previewWidth, params.previewHeight,  
  47.                 CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, &mPreviewStreamId);//創建一個Camera3OutputStream  
  48.         if (res != OK) {  
  49.             ALOGE("%s: Camera %d: Unable to create preview stream: %s (%d)",  
  50.                     __FUNCTION__, mId, strerror(-res), res);  
  51.             return res;  
  52.         }  
  53.     }  
  54.   
  55.     res = device->setStreamTransform(mPreviewStreamId,  
  56.             params.previewTransform);  
  57.     if (res != OK) {  
  58.         ALOGE("%s: Camera %d: Unable to set preview stream transform: "  
  59.                 "%s (%d)", __FUNCTION__, mId, strerror(-res), res);  
  60.         return res;  
  61.     }  
  62.   
  63.     return OK;  
  64. }  
該函數首先是查看當前StreamingProcessor模塊下是否存在Stream,沒有的話,則交由Camera3Device創建一個stream。顯然,一個StreamingProcessor只能擁有一個PreviewStream,而一個Camera3Device顯然控制着所有的Stream。

注意:在Camera2Client中,Stream大行其道,5大模塊的數據交互均以stream作爲基礎。

下面我們來重點關注Camera3Device的接口createStream,他是5個模塊創建stream的基礎:

  1. status_t Camera3Device::createStream(sp<ANativeWindow> consumer,  
  2.         uint32_t width, uint32_t height, int format, int *id) {  
  3.     ATRACE_CALL();  
  4.     Mutex::Autolock il(mInterfaceLock);  
  5.     Mutex::Autolock l(mLock);  
  6.     ALOGV("Camera %d: Creating new stream %d: %d x %d, format %d",  
  7.             mId, mNextStreamId, width, height, format);  
  8.   
  9.     status_t res;  
  10.     bool wasActive = false;  
  11.   
  12.     switch (mStatus) {  
  13.         case STATUS_ERROR:  
  14.             CLOGE("Device has encountered a serious error");  
  15.             return INVALID_OPERATION;  
  16.         case STATUS_UNINITIALIZED:  
  17.             CLOGE("Device not initialized");  
  18.             return INVALID_OPERATION;  
  19.         case STATUS_UNCONFIGURED:  
  20.         case STATUS_CONFIGURED:  
  21.             // OK  
  22.             break;  
  23.         case STATUS_ACTIVE:  
  24.             ALOGV("%s: Stopping activity to reconfigure streams", __FUNCTION__);  
  25.             res = internalPauseAndWaitLocked();  
  26.             if (res != OK) {  
  27.                 SET_ERR_L("Can't pause captures to reconfigure streams!");  
  28.                 return res;  
  29.             }  
  30.             wasActive = true;  
  31.             break;  
  32.         default:  
  33.             SET_ERR_L("Unexpected status: %d", mStatus);  
  34.             return INVALID_OPERATION;  
  35.     }  
  36.     assert(mStatus != STATUS_ACTIVE);  
  37.   
  38.     sp<Camera3OutputStream> newStream;  
  39.     if (format == HAL_PIXEL_FORMAT_BLOB) {//圖片  
  40.         ssize_t jpegBufferSize = getJpegBufferSize(width, height);  
  41.         if (jpegBufferSize <= 0) {  
  42.             SET_ERR_L("Invalid jpeg buffer size %zd", jpegBufferSize);  
  43.             return BAD_VALUE;  
  44.         }  
  45.   
  46.         newStream = new Camera3OutputStream(mNextStreamId, consumer,  
  47.                 width, height, jpegBufferSize, format);//jpeg 緩存的大小  
  48.     } else {  
  49.         newStream = new Camera3OutputStream(mNextStreamId, consumer,  
  50.                 width, height, format);//Camera3OutputStream  
  51.     }  
  52.     newStream->setStatusTracker(mStatusTracker);  
  53.   
  54.     res = mOutputStreams.add(mNextStreamId, newStream);//一個streamid與Camera3OutputStream綁定  
  55.     if (res < 0) {  
  56.         SET_ERR_L("Can't add new stream to set: %s (%d)", strerror(-res), res);  
  57.         return res;  
  58.     }  
  59.   
  60.     *id = mNextStreamId++;//至少一個previewstream 一般還有CallbackStream  
  61.     mNeedConfig = true;  
  62.   
  63.     // Continue captures if active at start  
  64.     if (wasActive) {  
  65.         ALOGV("%s: Restarting activity to reconfigure streams", __FUNCTION__);  
  66.         res = configureStreamsLocked();  
  67.         if (res != OK) {  
  68.             CLOGE("Can't reconfigure device for new stream %d: %s (%d)",  
  69.                     mNextStreamId, strerror(-res), res);  
  70.             return res;  
  71.         }  
  72.         internalResumeLocked();  
  73.     }  
  74.     ALOGV("Camera %d: Created new stream", mId);  
  75.     return OK;  
  76. }  
該函數重點是關注一個new Camera3OutputStream,在Camera3Device主要存在Camera3OutputStream和Camera3InputStream
兩種stream,前者主要作爲HAL的輸出,是請求HAL填充數據的OutPutStream,後者是由Framework將Stream進行填充。無論是Preview、record還是capture均是從HAL層獲取數據,故都會以OutPutStream的形式存在,是我們關注的重點,後面在描述Preview的數據流時還會進一步的闡述。

每當創建一個OutPutStream後,相關的stream信息被push維護在一個mOutputStreams的KeyedVector<int, sp<camera3::Camera3OutputStreamInterface> >表中,分別是該stream在Camera3Device中創建時的ID以及Camera3OutputStream的sp值。同時對mNextStreamId記錄下一個Stream的ID號。

上述過程完成StreamingProcessor模塊中一個PreviewStream的創建,其中Camera3OutputStream創建時的ID值被返回記錄作爲mPreviewStreamId的值,此外每個Stream都會有一個對應的ANativeWindow,這裏稱之爲Consumer。


(2)mCallbackProcessor->updateStream(params)

對比StreamingProcessor模塊創建previewstream的過程,很容易定位到Callback模塊是需要建立一個callback流,同樣需要創建一個Camera3OutputStream來接收HAL返回的每一幀幀數據,是否需要callback可以通過callbackenable來控制。一般但預覽階段可能不需要回調每一幀的數據到APP,但涉及到相應的其他業務如視頻處理時,就需要進行callback的enable。

  1. status_t CallbackProcessor::updateStream(const Parameters ¶ms) {  
  2.     ATRACE_CALL();  
  3.     status_t res;  
  4.   
  5.     Mutex::Autolock l(mInputMutex);  
  6.   
  7.     sp<CameraDeviceBase> device = mDevice.promote();  
  8.     if (device == 0) {  
  9.         ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);  
  10.         return INVALID_OPERATION;  
  11.     }  
  12.   
  13.     // If possible, use the flexible YUV format  
  14.     int32_t callbackFormat = params.previewFormat;  
  15.     if (mCallbackToApp) {  
  16.         // TODO: etalvala: This should use the flexible YUV format as well, but  
  17.         // need to reconcile HAL2/HAL3 requirements.  
  18.         callbackFormat = HAL_PIXEL_FORMAT_YV12;  
  19.     } else if(params.fastInfo.useFlexibleYuv &&  
  20.             (params.previewFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP ||  
  21.              params.previewFormat == HAL_PIXEL_FORMAT_YV12) ) {  
  22.         callbackFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;  
  23.     }  
  24.   
  25.     if (!mCallbackToApp && mCallbackConsumer == 0) {  
  26.         // Create CPU buffer queue endpoint, since app hasn't given us one  
  27.         // Make it async to avoid disconnect deadlocks  
  28.         sp<IGraphicBufferProducer> producer;  
  29.         sp<IGraphicBufferConsumer> consumer;  
  30.         BufferQueue::createBufferQueue(&producer, &consumer);//BufferQueueProducer與BufferQueueConsumer  
  31.         mCallbackConsumer = new CpuConsumer(consumer, kCallbackHeapCount);  
  32.         mCallbackConsumer->setFrameAvailableListener(this);//當前CallbackProcessor繼承於CpuConsumer::FrameAvailableListener  
  33.         mCallbackConsumer->setName(String8("Camera2Client::CallbackConsumer"));  
  34.         mCallbackWindow = new Surface(producer);//用於queue操作,這裏直接進行本地的buffer操作  
  35.     }  
  36.   
  37.     if (mCallbackStreamId != NO_STREAM) {  
  38.         // Check if stream parameters have to change  
  39.         uint32_t currentWidth, currentHeight, currentFormat;  
  40.         res = device->getStreamInfo(mCallbackStreamId,  
  41.                 ¤tWidth, ¤tHeight, ¤tFormat);  
  42.         if (res != OK) {  
  43.             ALOGE("%s: Camera %d: Error querying callback output stream info: "  
  44.                     "%s (%d)", __FUNCTION__, mId,  
  45.                     strerror(-res), res);  
  46.             return res;  
  47.         }  
  48.         if (currentWidth != (uint32_t)params.previewWidth ||  
  49.                 currentHeight != (uint32_t)params.previewHeight ||  
  50.                 currentFormat != (uint32_t)callbackFormat) {  
  51.             // Since size should only change while preview is not running,  
  52.             // assuming that all existing use of old callback stream is  
  53.             // completed.  
  54.             ALOGV("%s: Camera %d: Deleting stream %d since the buffer "  
  55.                     "parameters changed", __FUNCTION__, mId, mCallbackStreamId);  
  56.             res = device->deleteStream(mCallbackStreamId);  
  57.             if (res != OK) {  
  58.                 ALOGE("%s: Camera %d: Unable to delete old output stream "  
  59.                         "for callbacks: %s (%d)", __FUNCTION__,  
  60.                         mId, strerror(-res), res);  
  61.                 return res;  
  62.             }  
  63.             mCallbackStreamId = NO_STREAM;  
  64.         }  
  65.     }  
  66.   
  67.     if (mCallbackStreamId == NO_STREAM) {  
  68.         ALOGV("Creating callback stream: %d x %d, format 0x%x, API format 0x%x",  
  69.                 params.previewWidth, params.previewHeight,  
  70.                 callbackFormat, params.previewFormat);  
  71.         res = device->createStream(mCallbackWindow,  
  72.                 params.previewWidth, params.previewHeight,  
  73.                 callbackFormat, &mCallbackStreamId);//Creating callback stream  
  74.         if (res != OK) {  
  75.             ALOGE("%s: Camera %d: Can't create output stream for callbacks: "  
  76.                     "%s (%d)", __FUNCTION__, mId,  
  77.                     strerror(-res), res);  
  78.             return res;  
  79.         }  
  80.     }  
  81.   
  82.     return OK;  
  83. }  
對比updatePreviewStream可以發現,該函數自助創建了一套surface/BufferQueue/CpuConsumer的機制,這套類似SurfaceFlinger的buffer管理機制可參看一文Android5.1中surface生產者和消費者間的處理框架簡述。此外通過createStream請求Camera3Device建立一個Stream,其中Stream的ID值保存在mCallBackStreamId當中,並將一個CallbackWindow和當前的Stream綁定。

通過這個對比,也需要重點關注到,對於每個Camera3OutPutStream來說,每一個stream都被一個Consumer,而在此處都是Surface(ANativeWindow)所擁有,這個Consumer和HAL相匹配來說是消費者,但對於真正的處理Buffer的Consumer來說如CPUConsumer,Surface卻又是以一個Product的角色存在的。


(3)updateProcessorStream(mJpegProcessor, params)

  1. status_t Camera2Client::updateProcessorStream(sp<ProcessorT> processor,  
  2.                                               camera2::Parameters params) {  
  3.     // No default template arguments until C++11, so we need this overload  
  4.     return updateProcessorStream<ProcessorT, &ProcessorT::updateStream>(  
  5.             processor, params);  
  6. }  
  7. template <typename ProcessorT,  
  8.           status_t (ProcessorT::*updateStreamF)(const Parameters &)>  
  9. status_t Camera2Client::updateProcessorStream(sp<ProcessorT> processor,  
  10.                                               Parameters params) {  
  11.     status_t res;  
  12.   
  13.     // Get raw pointer since sp<T> doesn't have operator->*  
  14.     ProcessorT *processorPtr = processor.get();  
  15.     res = (processorPtr->*updateStreamF)(params);  
  16. .......  
  17. }  
該模板函數處理過程最終通過非顯示實例到顯示實例調用JpegProcessor::updateStream,該函數處理的邏輯基本和Callback模塊處理一致,創建的一個OutPutStream和CaptureWindow相互綁定,同時Stream的ID保存在mCaptureStreamId中。

此外需要說明一點:

在preview模式下,就去創建一個jpeg處理的stream,目的在於啓動takepicture時,可以更快的進行capture操作。是通過犧牲內存空間來提升效率。


(4)整合startPreviewL中所有的stream 到Vector<int32_t> outputStreams

outputStreams.push(getPreviewStreamId());//預覽stream

outputStreams.push(getCallbackStreamId())//Callback stream

目前一次Preview構建的stream數目至少爲兩個。


(5)mStreamingProcessor->updatePreviewRequest()

在創建好多路stream後,由StreamingProcessor模塊來將所有的stream信息交由Camera3Device去打包成Request請求。

注意:

Camera HAL2/3的特點是:將所有stream的請求都轉化爲幾個典型的Request請求,而這些Request需要由HAL去解析,進而處理所需的業務。這也是Camera3數據處理複雜化的原因所在。

  1. status_t StreamingProcessor::updatePreviewRequest(const Parameters ¶ms) {  
  2.     ATRACE_CALL();  
  3.     status_t res;  
  4.     sp<CameraDeviceBase> device = mDevice.promote();  
  5.     if (device == 0) {  
  6.         ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);  
  7.         return INVALID_OPERATION;  
  8.     }  
  9.   
  10.     Mutex::Autolock m(mMutex);  
  11.     if (mPreviewRequest.entryCount() == 0) {  
  12.         sp<Camera2Client> client = mClient.promote();  
  13.         if (client == 0) {  
  14.             ALOGE("%s: Camera %d: Client does not exist", __FUNCTION__, mId);  
  15.             return INVALID_OPERATION;  
  16.         }  
  17.   
  18.         // Use CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG for ZSL streaming case.  
  19.         if (client->getCameraDeviceVersion() >= CAMERA_DEVICE_API_VERSION_3_0) {  
  20.             if (params.zslMode && !params.recordingHint) {  
  21.                 res = device->createDefaultRequest(CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG,  
  22.                         &mPreviewRequest);  
  23.             } else {  
  24.                 res = device->createDefaultRequest(CAMERA3_TEMPLATE_PREVIEW,  
  25.                         &mPreviewRequest);  
  26.             }  
  27.         } else {  
  28.             res = device->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,  
  29.                     &mPreviewRequest);//創建一個Preview相關的request,由底層的hal來完成default創建  
  30.         }  
  31.   
  32.         if (res != OK) {  
  33.             ALOGE("%s: Camera %d: Unable to create default preview request: "  
  34.                     "%s (%d)", __FUNCTION__, mId, strerror(-res), res);  
  35.             return res;  
  36.         }  
  37.     }  
  38.   
  39.     res = params.updateRequest(&mPreviewRequest);//根據參數來更新CameraMetadata request  
  40.     if (res != OK) {  
  41.         ALOGE("%s: Camera %d: Unable to update common entries of preview "  
  42.                 "request: %s (%d)", __FUNCTION__, mId,  
  43.                 strerror(-res), res);  
  44.         return res;  
  45.     }  
  46.   
  47.     res = mPreviewRequest.update(ANDROID_REQUEST_ID,  
  48.             &mPreviewRequestId, 1);//mPreviewRequest的ANDROID_REQUEST_ID  
  49.     if (res != OK) {  
  50.         ALOGE("%s: Camera %d: Unable to update request id for preview: %s (%d)",  
  51.                 __FUNCTION__, mId, strerror(-res), res);  
  52.         return res;  
  53.     }  
  54.   
  55.     return OK;  
  56. }<span style="color:#ff0000;">  
  57. </span>  
該函數的處理過程是一個構建並初始化mPreviewRequest的過程,分以下幾個流程來分析:

a mPreviewRequest是一個CameraMetadata類型數據,用於封裝當前previewRequest。


b device->createDefaultRequest(CAMERA3_TEMPLATE_PREVIEW, &mPreviewRequest)

  1. const camera_metadata_t *rawRequest;  
  2.  ATRACE_BEGIN("camera3->construct_default_request_settings");  
  3.  rawRequest = mHal3Device->ops->construct_default_request_settings(  
  4.      mHal3Device, templateId);  
  5.  ATRACE_END();  
  6.  if (rawRequest == NULL) {  
  7.      SET_ERR_L("HAL is unable to construct default settings for template %d",  
  8.              templateId);  
  9.      return DEAD_OBJECT;  
  10.  }  
  11.  *request = rawRequest;  
  12.  mRequestTemplateCache[templateId] = rawRequest;  
最終是由hal來實現構建一個rawrequest,即對於Preview,而言是構建了一個CAMERA3_TEMPLATE_PREVIEW類型的Request。其實對HAL而言,rawrequest本質是用於操作一個camera_metadata_t類型的數據:

  1. struct camera_metadata {  
  2.     metadata_size_t          size;  
  3.     uint32_t                 version;  
  4.     uint32_t                 flags;  
  5.     metadata_size_t          entry_count;  
  6.     metadata_size_t          entry_capacity;  
  7.     metadata_uptrdiff_t      entries_start; // Offset from camera_metadata  
  8.     metadata_size_t          data_count;  
  9.     metadata_size_t          data_capacity;  
  10.     metadata_uptrdiff_t      data_start; // Offset from camera_metadata  
  11.     uint8_t                  reserved[];  
  12. };  
該數據結構可以存儲多種數據,且可以根據entry tag的不同類型來存儲數據,同時數據量的大小也可以自動調整。


c mPreviewRequest.update(ANDROID_REQUEST_ID,&mPreviewRequestId, 1)

將當前的PreviewRequest相應的ID保存到camera metadata。


(6)mStreamingProcessor->startStream啓動整個預覽的stream流

該函數的處理過程較爲複雜,可以說是整個Preview正常工作的核心控制

  1. status_t StreamingProcessor::startStream(StreamType type,  
  2.         const Vector<int32_t> &outputStreams) {  
  3. .....  
  4. CameraMetadata &request = (type == PREVIEW) ?  
  5.             mPreviewRequest : mRecordingRequest;//取preview的CameraMetadata request  
  6. ....res = request.update(  
  7.     ANDROID_REQUEST_OUTPUT_STREAMS,  
  8.         outputStreams);//CameraMetadata中添加outputStreams  
  9.  res = device->setStreamingRequest(request);//向hal發送request  
  10. .....  
  11. }  

該函數首先是根據當前工作模式來確定StreamingProcessor需要處理的Request,該模塊負責Preview和Record兩個Request。

以PreviewRequest就是之前createDefaultRequest構建的,這裏先是將這個Request所需要操作的Outputstream打包到一個tag叫ANDROID_REQUEST_OUTPUT_STREAMS的entry當中。


a:setStreamingRequest

真正的請求Camera3Device去處理這個帶有多路stream的PreviewRequest。

  1. status_t Camera3Device::setStreamingRequest(const CameraMetadata &request,  
  2.                                             int64_t* /*lastFrameNumber*/) {  
  3.     ATRACE_CALL();  
  4.   
  5.     List<const CameraMetadata> requests;  
  6.     requests.push_back(request);  
  7.     return setStreamingRequestList(requests, /*lastFrameNumber*/NULL);  
  8. }  
該函數將mPreviewRequest push到一個list,調用setStreamingRequestList

  1. status_t Camera3Device::setStreamingRequestList(const List<const CameraMetadata> &requests,  
  2.                                                 int64_t *lastFrameNumber) {  
  3.     ATRACE_CALL();  
  4.   
  5.     return submitRequestsHelper(requests, /*repeating*/true, lastFrameNumber);  
  6. }  

  1. status_t Camera3Device::submitRequestsHelper(  
  2.         const List<const CameraMetadata> &requests, bool repeating,  
  3.         /*out*/  
  4.         int64_t *lastFrameNumber) {//repeating = 1;lastFrameNumber = NULL  
  5.     ATRACE_CALL();  
  6.     Mutex::Autolock il(mInterfaceLock);  
  7.     Mutex::Autolock l(mLock);  
  8.   
  9.     status_t res = checkStatusOkToCaptureLocked();  
  10.     if (res != OK) {  
  11.         // error logged by previous call  
  12.         return res;  
  13.     }  
  14.   
  15.     RequestList requestList;  
  16.   
  17.     res = convertMetadataListToRequestListLocked(requests, /*out*/&requestList);//返回的是CaptureRequest RequestList  
  18.     if (res != OK) {  
  19.         // error logged by previous call  
  20.         return res;  
  21.     }  
  22.   
  23.     if (repeating) {  
  24.         res = mRequestThread->setRepeatingRequests(requestList, lastFrameNumber);//重複的request存入到RequestThread  
  25.     } else {  
  26.         res = mRequestThread->queueRequestList(requestList, lastFrameNumber);//capture模式,拍照單詞  
  27.     }  
  28.   
  29.     if (res == OK) {  
  30.         waitUntilStateThenRelock(/*active*/true, kActiveTimeout);  
  31.         if (res != OK) {  
  32.             SET_ERR_L("Can't transition to active in %f seconds!",  
  33.                     kActiveTimeout/1e9);  
  34.         }  
  35.         ALOGV("Camera %d: Capture request %" PRId32 " enqueued", mId,  
  36.               (*(requestList.begin()))->mResultExtras.requestId);  
  37.     } else {  
  38.         CLOGE("Cannot queue request. Impossible.");  
  39.         return BAD_VALUE;  
  40.     }  
  41.   
  42.     return res;  
  43. }  
b convertMetadataListToRequestListLocked

這個函數是需要將Requestlist中保存的CameraMetadata數據轉換爲List<sp<CaptureRequest> >

  1. status_t Camera3Device::convertMetadataListToRequestListLocked(  
  2.         const List<const CameraMetadata> &metadataList, RequestList *requestList) {  
  3.     if (requestList == NULL) {  
  4.         CLOGE("requestList cannot be NULL.");  
  5.         return BAD_VALUE;  
  6.     }  
  7.   
  8.     int32_t burstId = 0;  
  9.     for (List<const CameraMetadata>::const_iterator it = metadataList.begin();//CameraMetadata, mPreviewRequest  
  10.             it != metadataList.end(); ++it) {  
  11.         sp<CaptureRequest> newRequest = setUpRequestLocked(*it);//新建CaptureRequest由CameraMetadata轉化而來  
  12.         if (newRequest == 0) {  
  13.             CLOGE("Can't create capture request");  
  14.             return BAD_VALUE;  
  15.         }  
  16.   
  17.         // Setup burst Id and request Id  
  18.         newRequest->mResultExtras.burstId = burstId++;  
  19.         if (it->exists(ANDROID_REQUEST_ID)) {  
  20.             if (it->find(ANDROID_REQUEST_ID).count == 0) {  
  21.                 CLOGE("RequestID entry exists; but must not be empty in metadata");  
  22.                 return BAD_VALUE;  
  23.             }  
  24.             newRequest->mResultExtras.requestId = it->find(ANDROID_REQUEST_ID).data.i32[0];//設置該request對應的id  
  25.         } else {  
  26.             CLOGE("RequestID does not exist in metadata");  
  27.             return BAD_VALUE;  
  28.         }  
  29.   
  30.         requestList->push_back(newRequest);  
  31.   
  32.         ALOGV("%s: requestId = %" PRId32, __FUNCTION__, newRequest->mResultExtras.requestId);  
  33.     }  
  34.     return OK;  
  35. }  
這裏是對List<const CameraMetadata>進行迭代解析處理,如當前模式下僅存在PreviewRequest這一個CameraMetadata,通過setUpRequestLocked將其轉換爲一個CaptureRequest。


c 重點來關注setUpRequestLocked複雜的處理過程

  1. sp<Camera3Device::CaptureRequest> Camera3Device::setUpRequestLocked(  
  2.         const CameraMetadata &request) {//mPreviewRequest  
  3.     status_t res;  
  4.   
  5.     if (mStatus == STATUS_UNCONFIGURED || mNeedConfig) {  
  6.         res = configureStreamsLocked();  
  7.       ......<strong>  
  8.     </strong>sp<CaptureRequest> newRequest = createCaptureRequest(request);//CameraMetadata轉爲CaptureRequest,包含mOutputStreams  
  9.     return newRequest;  
  10. }  

configureStreamsLocked函數主要是將Camera3Device側建立的所有Stream包括Output與InPut格式的交由HAL3層的Device去實現處理的核心接口是configure_streams與register_stream_buffer。該部分內容會涉及到更多的數據流,詳細的處理過程會放在下一博文中進行分析。


createCaptureRequest函數是將一個CameraMetadata格式的數據如PreviewRequest轉換爲一個CaptureRequest:

  1. sp<Camera3Device::CaptureRequest> Camera3Device::createCaptureRequest(  
  2.         const CameraMetadata &request) {//mPreviewRequest  
  3.     ATRACE_CALL();  
  4.     status_t res;  
  5.   
  6.     sp<CaptureRequest> newRequest = new CaptureRequest;  
  7.     newRequest->mSettings = request;//CameraMetadata  
  8.   
  9.     camera_metadata_entry_t inputStreams =  
  10.             newRequest->mSettings.find(ANDROID_REQUEST_INPUT_STREAMS);  
  11.     if (inputStreams.count > 0) {  
  12.         if (mInputStream == NULL ||  
  13.                 mInputStream->getId() != inputStreams.data.i32[0]) {  
  14.             CLOGE("Request references unknown input stream %d",  
  15.                     inputStreams.data.u8[0]);  
  16.             return NULL;  
  17.         }  
  18.         // Lazy completion of stream configuration (allocation/registration)  
  19.         // on first use  
  20.         if (mInputStream->isConfiguring()) {  
  21.             res = mInputStream->finishConfiguration(mHal3Device);  
  22.             if (res != OK) {  
  23.                 SET_ERR_L("Unable to finish configuring input stream %d:"  
  24.                         " %s (%d)",  
  25.                         mInputStream->getId(), strerror(-res), res);  
  26.                 return NULL;  
  27.             }  
  28.         }  
  29.   
  30.         newRequest->mInputStream = mInputStream;  
  31.         newRequest->mSettings.erase(ANDROID_REQUEST_INPUT_STREAMS);  
  32.     }  
  33.   
  34.     camera_metadata_entry_t streams =  
  35.             newRequest->mSettings.find(ANDROID_REQUEST_OUTPUT_STREAMS);//讀取存儲在CameraMetadata的stream id信息  
  36.     if (streams.count == 0) {  
  37.         CLOGE("Zero output streams specified!");  
  38.         return NULL;  
  39.     }  
  40.   
  41.     for (size_t i = 0; i < streams.count; i++) {  
  42.         int idx = mOutputStreams.indexOfKey(streams.data.i32[i]);//Camera3OutputStream的id在mOutputStreams中  
  43.         if (idx == NAME_NOT_FOUND) {  
  44.             CLOGE("Request references unknown stream %d",  
  45.                     streams.data.u8[i]);  
  46.             return NULL;  
  47.         }  
  48.         sp<Camera3OutputStreamInterface> stream =  
  49.                 mOutputStreams.editValueAt(idx);//返回的是Camera3OutputStream,preview/callback等stream  
  50.   
  51.         // Lazy completion of stream configuration (allocation/registration)  
  52.         // on first use  
  53.         if (stream->isConfiguring()) {//STATE_IN_CONFIG或者STATE_IN_RECONFIG  
  54.             res = stream->finishConfiguration(mHal3Device);//register_stream_buffer, STATE_CONFIGURED  
  55.             if (res != OK) {  
  56.                 SET_ERR_L("Unable to finish configuring stream %d: %s (%d)",  
  57.                         stream->getId(), strerror(-res), res);  
  58.                 return NULL;  
  59.             }  
  60.         }  
  61.   
  62.         newRequest->mOutputStreams.push(stream);//Camera3OutputStream添加到CaptureRequest的mOutputStreams  
  63.     }  
  64.     newRequest->mSettings.erase(ANDROID_REQUEST_OUTPUT_STREAMS);  
  65.   
  66.     return newRequest;  
  67. }  
該函數主要處理指定的這個CameraMetadata mPreviewRequest下對應所擁有的Output與Input Stream,對於Preview而言,至少存在OutPutStream包括一路StreamProcessor與一路可選的CallbackProcessor。

在構建這個PreviewRequest時,已經將ANDROID_REQUEST_OUTPUT_STREAMS這個Tag進行了初始化,相應的內容爲Vector<int32_t> &outputStreams,包含着屬於PreviewRequest這個Request所需要的輸出stream的ID值,通過這個ID index值,可以遍歷到Camera3Device下所createstream創造的Camera3OutputStream,即說明不同類型的Request在Camera3Device端存在多個Stream,而每次不同業務下所需要Request的對應的Stream又僅是其中的個別而已。

idx =  mOutputStreams.indexOfKey(streams.data.i32[i])是通過屬於PreviewRequest中包含的一個stream的ID值來查找到mOutputStreams這個KeyedVector中對應的標定值index。注意:兩個索引值不一定是一致的。

mOutputStreams.editValueAt(idx)是獲取一個與該ID值(如Previewstream ID、Callback Stream ID等等)相對應的Camera3OutputStream。


在找到了當前Request中所有的Camera3OutputStream後,將其維護在CaptureRequest中

  1. class CaptureRequest : public LightRefBase<CaptureRequest> {  
  2.       public:  
  3.         CameraMetadata                      mSettings;  
  4.         sp<camera3::Camera3Stream>          mInputStream;  
  5.         Vector<sp<camera3::Camera3OutputStreamInterface> >  
  6.                                             mOutputStreams;  
  7.         CaptureResultExtras                 mResultExtras;  
  8.     };  
mSettings是保存CameraMetadata PreviewRequest,vector mOutPutStreams保存着當前Request提取出來的Camera3OutputStream,至此構建了一個CaptureRequest。


返回到convertMetadataListToRequestListLocked中,現在已經完成了一個CameraMetadata Request的處理,生產的是一個CaptureRequest。我們將這個ANDROID_REQUEST_ID的ID值,保留在

newRequest->mResultExtras.requestId = it->find(ANDROID_REQUEST_ID).data.i32[0]。

這個值在整個Camera3的架構中,僅存在3大種Request類型,說明了整個和HAL層交互的Request類型是不多的:

預覽Request mPreviewRequest:        mPreviewRequestId(Camera2Client::kPreviewRequestIdStart),

拍照Request mCaptureRequest:mCaptureId(Camera2Client::kCaptureRequestIdStart),

錄像Request mRecordingRequest:        mRecordingRequestId(Camera2Client::kRecordingRequestIdStart),

  1. static const int32_t kPreviewRequestIdStart = 10000000;  
  2. static const int32_t kPreviewRequestIdEnd   = 20000000;  
  3. static const int32_t kRecordingRequestIdStart  = 20000000;  
  4. static const int32_t kRecordingRequestIdEnd    = 30000000;  
  5. static const int32_t kCaptureRequestIdStart = 30000000;  
  6. static const int32_t kCaptureRequestIdEnd   = 40000000;  
至此執行requestList->push_back(newRequest)後生成了一個requestList,本質上可以先認爲這次僅是含有PreviewRequest相關的內容。


d mRequestThread->setRepeatingRequests(requestList)

對於Preview來說,一次Preview後底層硬件就該可以連續的工作,而不需要進行過多的切換,故Framework每次向HAL發送的Request均是一種repeat的操作模式,故調用了一個重複的RequestQueue來循環處理每次的Request。

  1. status_t Camera3Device::RequestThread::setRepeatingRequests(  
  2.         const RequestList &requests,  
  3.         /*out*/  
  4.         int64_t *lastFrameNumber) {  
  5.     Mutex::Autolock l(mRequestLock);  
  6.     if (lastFrameNumber != NULL) {//第一次進來爲null  
  7.         *lastFrameNumber = mRepeatingLastFrameNumber;  
  8.     }  
  9.     mRepeatingRequests.clear();  
  10.     mRepeatingRequests.insert(mRepeatingRequests.begin(),  
  11.             requests.begin(), requests.end());  
  12.   
  13.     unpauseForNewRequests();//signal request_thread in waitfornextrequest  
  14.   
  15.     mRepeatingLastFrameNumber = NO_IN_FLIGHT_REPEATING_FRAMES;  
  16.     return OK;  
  17. }  
將Preview線程提交的Request加入到mRepeatingRequests中後,喚醒RequestThread線程去處理當前新的Request。


(7) RequestThread 請求處理線程

RequestThread::threadLoop()函數主要用於響應並處理新加入到Request隊列中的請求。

  1. bool Camera3Device::RequestThread::threadLoop() {  
  2. ....  
  3.     sp<CaptureRequest> nextRequest = waitForNextRequest();//返回的是mRepeatingRequests,mPreviewRequest  
  4.     if (nextRequest == NULL) {  
  5.         return true;  
  6.     }  
  7.     // Create request to HAL  
  8.     camera3_capture_request_t request = camera3_capture_request_t();//CaptureRequest轉爲給HAL3.0的camera3_capture_request_t  
  9.     request.frame_number = nextRequest->mResultExtras.frameNumber;//當前幀號  
  10.     Vector<camera3_stream_buffer_t> outputBuffers;  
  11.     // Get the request ID, if any  
  12.     int requestId;  
  13.     camera_metadata_entry_t requestIdEntry =  
  14.             nextRequest->mSettings.find(ANDROID_REQUEST_ID);  
  15.     if (requestIdEntry.count > 0) {  
  16.         requestId = requestIdEntry.data.i32[0];//獲取requestid,這裏是mPreviewRequest的id  
  17.     } else {  
  18.         ALOGW("%s: Did not have android.request.id set in the request",  
  19.                 __FUNCTION__);  
  20.         requestId = NAME_NOT_FOUND;  
  21.     }  
  22.  .....  
  23.     camera3_stream_buffer_t inputBuffer;  
  24.     uint32_t totalNumBuffers = 0;  
  25. .....  
  26.     // Submit request and block until ready for next one  
  27.     ATRACE_ASYNC_BEGIN("frame capture", request.frame_number);  
  28.     ATRACE_BEGIN("camera3->process_capture_request");  
  29.     res = mHal3Device->ops->process_capture_request(mHal3Device, &request);//調用底層的process_capture_request  
  30.     ATRACE_END();  
  31.   
  32.    .......  
  33. }  
函數主體內容較爲複雜,分以下幾個部分來說明他的響應邏輯:

(7.1) waitForNextRequest()

  1.     Camera3Device::RequestThread::waitForNextRequest() {  
  2. status_t res;  
  3. sp<CaptureRequest> nextRequest;  
  4.   
  5. // Optimized a bit for the simple steady-state case (single repeating  
  6. // request), to avoid putting that request in the queue temporarily.  
  7. Mutex::Autolock l(mRequestLock);  
  8.   
  9. while (mRequestQueue.empty()) {  
  10.     if (!mRepeatingRequests.empty()) {  
  11.         // Always atomically enqueue all requests in a repeating request  
  12.         // list. Guarantees a complete in-sequence set of captures to  
  13.         // application.  
  14.         const RequestList &requests = mRepeatingRequests;  
  15.         RequestList::const_iterator firstRequest =  
  16.                 requests.begin();  
  17.         nextRequest = *firstRequest;//取  
  18.         mRequestQueue.insert(mRequestQueue.end(),  
  19.                 ++firstRequest,  
  20.                 requests.end());//把當前的mRepeatingRequests插入到mRequestQueue  
  21.         // No need to wait any longer  
  22.   
  23.         mRepeatingLastFrameNumber = mFrameNumber + requests.size() - 1;  
  24.   
  25.         break;  
  26.     }  
  27.   
  28.     res = mRequestSignal.waitRelative(mRequestLock, kRequestTimeout);//等待下一個request  
  29.   
  30.     if ((mRequestQueue.empty() && mRepeatingRequests.empty()) ||  
  31.             exitPending()) {  
  32.         Mutex::Autolock pl(mPauseLock);  
  33.         if (mPaused == false) {  
  34.             ALOGV("%s: RequestThread: Going idle", __FUNCTION__);  
  35.             mPaused = true;  
  36.             // Let the tracker know  
  37.             sp<StatusTracker> statusTracker = mStatusTracker.promote();  
  38.             if (statusTracker != 0) {  
  39.                 statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);  
  40.             }  
  41.         }  
  42.         // Stop waiting for now and let thread management happen  
  43.         return NULL;  
  44.     }  
  45. }  
  46.   
  47. if (nextRequest == NULL) {  
  48.     // Don't have a repeating request already in hand, so queue  
  49.     // must have an entry now.  
  50.     RequestList::iterator firstRequest =  
  51.             mRequestQueue.begin();  
  52.     nextRequest = *firstRequest;  
  53.     mRequestQueue.erase(firstRequest);//取一根mRequestQueue中的CaptureRequest,來自於mRepeatingRequests的next  
  54. }  
  55.   
  56. // In case we've been unpaused by setPaused clearing mDoPause, need to  
  57. // update internal pause state (capture/setRepeatingRequest unpause  
  58. // directly).  
  59. Mutex::Autolock pl(mPauseLock);  
  60. if (mPaused) {  
  61.     ALOGV("%s: RequestThread: Unpaused", __FUNCTION__);  
  62.     sp<StatusTracker> statusTracker = mStatusTracker.promote();  
  63.     if (statusTracker != 0) {  
  64.         statusTracker->markComponentActive(mStatusId);  
  65.     }  
  66. }  
  67. mPaused = false;  
  68.   
  69. // Check if we've reconfigured since last time, and reset the preview  
  70. // request if so. Can't use 'NULL request == repeat' across configure calls.  
  71. if (mReconfigured) {  
  72.     mPrevRequest.clear();  
  73.     mReconfigured = false;  
  74. }  
  75.   
  76. if (nextRequest != NULL) {  
  77.     nextRequest->mResultExtras.frameNumber = mFrameNumber++;//對每一個非空的request需要幀號++  
  78.     nextRequest->mResultExtras.afTriggerId = mCurrentAfTriggerId;  
  79.     nextRequest->mResultExtras.precaptureTriggerId = mCurrentPreCaptureTriggerId;  
  80. }  
  81. return nextRequest;  
該函數是響應RequestList的核心,通過不斷的輪訓休眠等待一旦mRepeatingRequests有Request可處理時,就將他內部所有的CaptureRequest加入到mRequestQueue 中去,理論來說每一個CaptureRequest對應着一幀的請求處理,每次響應時可能會出現mRequestQueue包含了多個CaptureRequest。

通過nextRequest->mResultExtras.frameNumber = mFrameNumber++表示當前CaptureRequest在處理的一幀圖像號。

對於mRepeatingRequests而言,只有其非空,在執行完一次queue操作後,在循環進入執行時,會自動對mRequestQueue進行erase操作,是的mRequestQueue變爲empty後再次重新加載mRepeatingRequests中的內容,從而形成一個隊repeatRequest的重複響應過程。


(7.2)   camera_metadata_entry_t requestIdEntry = nextRequest->mSettings.find(ANDROID_REQUEST_ID);提取該CaptureRequest對應的Request 類型值


(7.3) getBuffer操作

涉及到比較複雜的數據流操作過程的內容見下一博文


(7.4) mHal3Device->ops->process_capture_request(mHal3Device, &request)

這裏的request是已經由一個CaptureRequest轉換爲和HAL3.0交互的camera3_capture_request_t結構。



8 小結

至此已經完成了一次向HAL3.0 Device發送一次完整的Request的請求。從最初Preview啓動建立多個OutPutStream,再是將這些Stream打包成一個mPreviewRequest來啓動stream,隨後將這個Request又轉變爲一個CaptureRequest,直到轉爲Capture list後交由RequestThread來處理這些請求。每一次的Request簡單可以說是Camera3Device向HAL3.0請求一幀數據,當然每一次Request也可以包含各種控制操作,如AutoFocus等內容,會在後續補充。

到這裏從StartPreview的入口開始,直到相應的Request下發到HAL3.0,基本描述了一次完成的控制流的處理。對於較爲複雜的數據流本質也是一併合併在這個控制操作中的,但作爲Buffer視頻緩存流的管理維護將在下一博文進行描述與總結。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章