Camera Framework流程系列(一)setRepeatingRequest 流程

发布时间:2026/10/8 1:23:51
Camera Framework流程系列(一)setRepeatingRequest 流程 在安卓 Camera Framework 中setRepeatingRequest 是一个关键的 API用于设置重复的捕获请求。它允许应用层通过 CameraCaptureSession 发起连续的预览或录制请求。以下是关于 setRepeatingRequest 的详细流程解析。1. 调用链概述应用层调用 CameraCaptureSession.setRepeatingRequest 方法时会触发框架层和 HAL 层的一系列交互。具体流程如下应用层通过 CameraManager.openCamera() 获取到 CameraDevice 实例。在 CameraDevice 创建后应用层通过 createCaptureSession() 创建 CameraCaptureSession。应用层调用CameraCaptureSession的setRepeatingRequest 方法发起预览请求。相机框架Camera3Device中收到应用下发下来的RepeatingRequest后会不断地下发预览request给Camera HAL。一般情况下应用只需要调用一次setRepeatingRequest接口即可实现预览Camera3Device会实现重复下发request的动作。但是如果预览CaptureRequest的setting有变化比如需要改变sensor、lens、flash或3A相关的metadata参数就需要重新调用一次setRepeatingRequest接口将新的CaptureRequest下发下去。2. 具体实现分析java层流程CaptureRequest本质是对Settings和Output Surfaces的封装具体介绍可参考第23讲 CaptureRequest详解 - Android Camera2 API|极客笔记。CameraCaptureSessionImpl#setRepeatingRequest public int setRepeatingRequest(CaptureRequest request, CaptureCallback callback, Handler handler) throws CameraAccessException { checkRepeatingRequest(request); synchronized (mDeviceImpl.mInterfaceLock) { checkNotClosed(); handler checkHandler(handler, callback); if (DEBUG) { Log.v(TAG, mIdString setRepeatingRequest - request request , callback callback handler handler); } return addPendingSequence(mDeviceImpl.setRepeatingRequest(request, createCaptureCallbackProxy(handler, callback), mDeviceExecutor)); } }1. CameraDeviceImpl#setRepeatingRequest public int setRepeatingRequest(CaptureRequest request, CaptureCallback callback, Executor executor) throws CameraAccessException { ListCaptureRequest requestList new ArrayListCaptureRequest(); requestList.add(request); return submitCaptureRequest(requestList, callback, executor, /*streaming*/true); } 2. CameraDeviceImpl#submitCaptureRequest private int submitCaptureRequest(ListCaptureRequest requestList, CaptureCallback callback, Executor executor, boolean repeating) throws CameraAccessException { ...... // 如果是预览则调用stopRepeating通知cameraserver停止像HAL发送预览request if (repeating) { stopRepeating(); } SubmitInfo requestInfo; CaptureRequest[] requestArray requestList.toArray(new CaptureRequest[requestList.size()]); ...... // 调用native FWK层submitRequestList接口下发request requestInfo mRemoteDevice.submitRequestList(requestArray, repeating); ...... return requestInfo.getRequestId(); } }封装在SubmitInfo对象中的两个变量mRequestId对应native层CameraDeviceClient的mRequestIdCounter计数器从0开始表示调用submitRequestList的次数。mLastFrameNumber第一次下repeating request的时候为-1。java层的CameraCharacteristic静态metadata、CaptureRequestsettingdynamic metadata、CaptureResult底层实际生效的metadynamic metadata对应到native层本质上都是CameraMetadata这三个类里面都封装了CameraMetadataNative成员属性来实现和native层对应上CameraCharacteristicprivate final CameraMetadataNative mPropertiesCaptureRequestprivate CameraMetadataNative mLogicalCameraSettings; private final HashMapString, CameraMetadataNative mPhysicalCameraSettingsCaptureResultprivate final CameraMetadataNative mResults。native层流程Camera3Device中的核心结构体类型class CaptureRequest : public LightRefBaseCaptureRequest { public: // cameraId metadata PhysicalCameraSettingsList mSettingsList; // surface信息流信息 Vectorspcamera3::Camera3OutputStreamInterface mOutputStreams; SurfaceMap mOutputSurfaces; CaptureResultExtras mResultExtras; // The number of requests that should be submitted to HAL at a time. // For example, if batch size is 8, this request and the following 7 // requests will be submitted to HAL at a time. The batch size for // the following 7 requests will be ignored by the request thread. // 默认为1只有高帧率录制场景会不一样 int mBatchSize; // 是否是预览request bool mRepeating; // request被创建的时间戳 nsecs_t mRequestTimeNs; ...... }; typedef ListspCaptureRequest RequestList; // Used to prepare a batch of requests. struct NextRequest { spCaptureRequest captureRequest;// Camera3Device中的request只有setting、surface和stream信息 camera_capture_request_t halRequest; // 给HAL下的request多了帧号和buffer句柄 Vectorcamera_stream_buffer_t outputBuffers; bool submitted; };InFlightRequest.h中的核心结构体类型typedef struct camera_capture_request { uint32_t frame_number; const camera_metadata_t *settings; uint32_t num_output_buffers; const camera_stream_buffer_t *output_buffers; uint32_t num_physcam_settings; const char **physcam_id; const camera_metadata_t **physcam_settings; } camera_capture_request_t; typedef struct camera_capture_result { uint32_t frame_number; const camera_metadata_t *result; uint32_t num_output_buffers; const camera_stream_buffer_t *output_buffers; uint32_t partial_result; uint32_t num_physcam_metadata; const char **physcam_ids; const camera_metadata_t **physcam_metadata; } camera_capture_result_t; typedef struct camera_shutter_msg { uint32_t frame_number; uint64_t timestamp; bool readout_timestamp_valid; uint64_t readout_timestamp; } camera_shutter_msg_t; struct InFlightRequest { // Set by notify() SHUTTER call. nsecs_t shutterTimestamp; // Set by process_capture_result(). nsecs_t sensorTimestamp; // The last metadata that framework receives from HAL and // not yet send out because the shutter event hasnt arrived. // Its added by process_capture_result and sent when framework // receives the shutter event. CameraMetadata pendingMetadata; // The metadata of the partial results that framework receives from HAL so far // and has sent out. CameraMetadata collectedPartialResult; // Buffers are added by process_capture_result when output buffers // return from HAL but framework has not yet received the shutter // event. They will be returned to the streams when framework receives // the shutter event. Vectorcamera_stream_buffer_t pendingOutputBuffers; // The physical camera ids being requested. // For request on a physical camera stream, the inside set contains one Id // For request on a stream group containing physical camera streams, the // inside set contains all stream Ids in the group. std::setstd::setstd::string physicalCameraIds; // Map of physicalCameraId - Metadata std::vectorPhysicalCaptureResultInfo physicalMetadatas; // Indicates a still capture request. bool stillCapture; // Indicates a ZSL capture request bool zslCapture; // What shared surfaces an output should go to SurfaceMap outputSurfaces; // Current output transformation int32_t transform; }; // Map from frame number to the in-flight request state typedef KeyedVectoruint32_t, InFlightRequest InFlightRequestMap;Camera3Device中的核心变量// Request相关 // mRequestQueue和mRepeatingRequests队列的关系如果mRequestQueue队列为空则从mRepeatingRequests队列复制一个request下个hal并将mRepeatingRequests队列中剩下的reqeust复制到mRequestQueue队列如果mRequestQueue队列不为空则从mRequestQueue队列取出一个request下个hal然后从该队列erase刚刚取出的request。 RequestList mRequestQueue:预览or拍照请求队列 RequestList mRepeatingRequests: 保存应用下发下来的预览CaptureRequest InFlightRequestMap mInFlightMap: 帧号、in-flight request的map集合缓存了已经发送但是还没有收到响应的ClientRequset VectorNextRequest mNextRequests: uint32_t mFrameNumber: 帧号从0开始 // SessionKey Vectorint32_t mSessionParamKeys: CameraMetadata mLatestSessionParams: // 用于threadLoop控制下request Mutex mPauseLock: Condition mDoPauseSignal: bool mDoPause: 用于是否暂停threadLoop流程。一般为false开始重新配流会设置为true配完流会重置为false bool mPaused:1将预览request插入到mRepeatingRequests队列的流程CameraDeviceClient的submitRequestList作为native层的入口将java层下发的requests封装成metadataRequestList和surfaceMapList后将其作为参数调用Camera3Device的setStreamingRequestList接口最终会清除mRepeatingRequests队列并将新请求插入该队列。binder::Status CameraDeviceClient::submitRequestList( const std::vectorhardware::camera2::CaptureRequest requests, bool streaming, /*out*/ hardware::camera2::utils::SubmitInfo *submitInfo) { Listconst CameraDeviceBase::PhysicalCameraSettingsList metadataRequestList; std::listSurfaceMap surfaceMapList; submitInfo-mRequestId mRequestIdCounter; uint32_t loopCounter 0; // 一般情况下requests的size都为1 for (auto request: requests) { SurfaceMap surfaceMap; Vectorint32_t outputStreamIds; std::vectorstd::string requestedPhysicalIds; int64_t dynamicProfileBitmap 0; if (request.mSurfaceList.size() 0) { for (const spSurface surface : request.mSurfaceList) { if (surface 0) continue; int32_t streamId; spIGraphicBufferProducer gbp surface-getIGraphicBufferProducer(); // 这里根据request携带的surface从之前配流保存的mStreamMap中获取到surfaceMap res insertGbpLocked(gbp, surfaceMap, outputStreamIds, streamId); } // 声明physicalSettingsList后面给其赋值 CameraDeviceBase::PhysicalCameraSettingsList physicalSettingsList; for (const auto it : request.mPhysicalCameraSettings) { physicalSettingsList.push_back({resolvedId, it.settings}); } if (!enforceRequestPermissions(physicalSettingsList.begin()-metadata)) { // Callee logs return STATUS_ERROR(CameraService::ERROR_PERMISSION_DENIED, Caller does not have permission to change restricted controls); } physicalSettingsList.begin()-metadata.update(ANDROID_REQUEST_OUTPUT_STREAMS, outputStreamIds[0], outputStreamIds.size()); if (request.mIsReprocess) { physicalSettingsList.begin()-metadata.update(ANDROID_REQUEST_INPUT_STREAMS, mInputStream.id, 1); } physicalSettingsList.begin()-metadata.update(ANDROID_REQUEST_ID, (submitInfo-mRequestId), /*size*/1); // 将requests中的setting和surface封装到metadataRequestList和surfaceMapList metadataRequestList.push_back(physicalSettingsList); surfaceMapList.push_back(surfaceMap); } // 计数器加1 mRequestIdCounter; if (streaming) { // 预览 err mDevice-setStreamingRequestList(metadataRequestList, surfaceMapList, (submitInfo-mLastFrameNumber)); mStreamingRequestId submitInfo-mRequestId; } else { // 拍照 err mDevice-captureList(metadataRequestList, surfaceMapList, (submitInfo-mLastFrameNumber)); } return res; }status_t Camera3Device::setStreamingRequestList( const Listconst PhysicalCameraSettingsList requestsList, const std::listSurfaceMap surfaceMaps, int64_t *lastFrameNumber) { ATRACE_CALL(); return submitRequestsHelper(requestsList, surfaceMaps, /*repeating*/true, lastFrameNumber); } status_t Camera3Device::submitRequestsHelper( const Listconst PhysicalCameraSettingsList requests, const std::listSurfaceMap surfaceMaps, bool repeating, /*out*/ int64_t *lastFrameNumber) { ATRACE_CALL(); nsecs_t requestTimeNs systemTime(); RequestList requestList; // 将requests转换成RequestList将PhysicalCameraSettingsList和SurfaceMap转换成Camera3Device定义的CaptureRequest res convertMetadataListToRequestListLocked(requests, surfaceMaps, repeating, requestTimeNs, /*out*/requestList); if (repeating) { res mRequestThread-setRepeatingRequests(requestList, lastFrameNumber); } else { res mRequestThread-queueRequestList(requestList, lastFrameNumber); } } status_t Camera3Device::RequestThread::setRepeatingRequests( const RequestList requests, /*out*/ int64_t *lastFrameNumber) { ATRACE_CALL(); Mutex::Autolock l(mRequestLock); if (lastFrameNumber ! NULL) { // mRepeatingLastFrameNumber初始值为-1也就是第一次下预览请求lastFrameNumber为-1 *lastFrameNumber mRepeatingLastFrameNumber; } // mRepeatingRequests: 类型为RequestList预览请求队列 mRepeatingRequests.clear(); mFirstRepeating true; mRepeatingRequests.insert(mRepeatingRequests.begin(), requests.begin(), requests.end()); unpauseForNewRequests(); mRepeatingLastFrameNumber hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES; return OK; }2Camera3Device::RequestThread::threadLoop()流程循环从请求队列取出请求并做prepareHalRequest操作后下发请求给HAL。bool Camera3Device::RequestThread::threadLoop() { ATRACE_CALL(); status_t res; // 如果mDoPause为false直接返回false // 如果mDoPause为true就会通过while循环和同步锁机制等待mDoPause被置为为false才退出循环返回false // 什么情况会wait正常情况mDoPause为false该接口直接返回false当重新配流时配流前设置为true此时threadLoop的流程进入到wait状态配完流后设置为falsethreadLoop重新进入工作状态。 if (waitIfPaused()) { return true; } // 从mRepeatingRequests队列或mRequestQueue队列取出一个NextRequest对象此时halReqeust还没ready并插入到mNextRequests队列 // 帧号先赋值给nextRequest然后1mFrameNumber waitForNextRequestBatch(); if (mNextRequests.size() 0) { return true; } ...... // 判断是否需要重配流 if (updateSessionParameters(mNextRequests[0].captureRequest-mSettingsList.begin()-metadata)) { } // 给mNextRequests队列中NextRequest的halRequest赋值buffer申请setting、帧号赋值 // 然后将这个request插入到mInFlightMap中 res prepareHalRequests(); // Submit a batch of requests to HAL. // Use flush lock only when submitting multilple requests in a batch. bool useFlushLock mNextRequests.size() 1; if (useFlushLock) { mFlushLock.lock(); } bool submitRequestSuccess false; nsecs_t tRequestStart systemTime(SYSTEM_TIME_MONOTONIC); // sendRequestsBatch给HAL下发request submitRequestSuccess sendRequestsBatch(); nsecs_t tRequestEnd systemTime(SYSTEM_TIME_MONOTONIC); mRequestLatency.add(tRequestStart, tRequestEnd); if (useFlushLock) { mFlushLock.unlock(); } // 清空mNextRequests队列 { Mutex::Autolock l(mRequestLock); mNextRequests.clear(); } mRequestSubmittedSignal.signal(); return submitRequestSuccess; }- waitForNextRequestBatch()流程从mRepeatingRequests队列或mRequestQueue队列取出一个NextRequest对象并插入到mNextRequests队列。mBatchSize不为1的高帧率录制场景则会插入多个请求同时下个halvoid Camera3Device::RequestThread::waitForNextRequestBatch() { ATRACE_CALL(); Mutex::Autolock l(mRequestLock); assert(mNextRequests.empty()); NextRequest nextRequest; // 针对预览总原则mRequestQueue中有request则从mRequestQueue中取否则从mRepeatingRequests中取。mRequestQueue中取一个删一个mRepeatingRequests中取只是复制操作。 // 1.如果应用下的是单个预览reqeust则直接从mRepeatingRequests队列复制该预览reqeust作为nextRequest返回。 // 2.如果应用下的是n个预览reqeust则会取从mRepeatingRequests队列中的第一个request作为nextRequest返回并将mRepeatingRequests队列中剩下的n-1个预览reqeust插入到mRequestQueue队列中下次下预览请求时则会开始从mRequestQueue队列取预览请求。mRequestQueue队列取完某个预览request会做erase的操作但mRepeatingRequests不会 // 该接口中会执行nextRequest-mResultExtras.frameNumber mFrameNumber; nextRequest.captureRequest waitForNextRequestLocked(); if (nextRequest.captureRequest nullptr) { return; } nextRequest.halRequest camera_capture_request_t(); nextRequest.submitted false; // 往mNextRequests添加NextRequest对象但此时halRequest还没做赋值 mNextRequests.add(nextRequest); // batchSize默认为1高帧率录制场景会不一样 const size_t batchSize nextRequest.captureRequest-mBatchSize; for (size_t i 1; i batchSize; i) { NextRequest additionalRequest; additionalRequest.captureRequest waitForNextRequestLocked(); if (additionalRequest.captureRequest nullptr) { break; } additionalRequest.halRequest camera_capture_request_t(); additionalRequest.submitted false; mNextRequests.add(additionalRequest); } if (mNextRequests.size() batchSize) { ALOGE(RequestThread: only get %zu out of %zu requests. Skipping requests., mNextRequests.size(), batchSize); cleanUpFailedRequests(/*sendRequestError*/true); } return; }-prepareHalRequests()流程prepare halRequest并将这个request插入到mInFlightMap中status_t Camera3Device::RequestThread::prepareHalRequests() { ATRACE_CALL(); bool batchedRequest mNextRequests[0].captureRequest-mBatchSize 1; for (size_t i 0; i mNextRequests.size(); i) { auto nextRequest mNextRequests.editItemAt(i); spCaptureRequest captureRequest nextRequest.captureRequest; camera_capture_request_t* halRequest nextRequest.halRequest; Vectorcamera_stream_buffer_t* outputBuffers nextRequest.outputBuffers; // Prepare a request to HAL halRequest-frame_number captureRequest-mResultExtras.frameNumber; ...... if (parent-isHalBufferManagedStream(streamId)) { if (outputStream-isAbandoned()) { ALOGV(%s: stream %d is abandoned, skipping request, __FUNCTION__, streamId); return TIMED_OUT; } // HAL will request buffer through requestStreamBuffer API camera_stream_buffer_t buffer outputBuffers-editItemAt(j); buffer.stream outputStream-asHalStream(); buffer.buffer nullptr; buffer.status CAMERA_BUFFER_STATUS_OK; buffer.acquire_fence -1; buffer.release_fence -1; // Mark the output stream as unpreparable to block clients from calling // prepare after this request reaches CameraHal and before the respective // buffers are requested. outputStream-markUnpreparable(); } else { // 如果没有使能hal buffer manager则申请buffer res outputStream-getBuffer(outputBuffers-editItemAt(j), waitDuration, captureRequest-mOutputSurfaces[streamId]); if (res ! OK) { // Cant get output buffer from gralloc queue - this could be due to // abandoned queue or other consumer misbehavior, so not a fatal // error ALOGV(RequestThread: Cant get output buffer, skipping request: %s (%d), strerror(-res), res); return TIMED_OUT; } } // 如果是拍照 if (!mNextRequests[0].captureRequest-mSettingsList.begin()-metadata.isEmpty()) { camera_metadata_ro_entry_t e camera_metadata_ro_entry_t(); find_camera_metadata_ro_entry(settings, ANDROID_CONTROL_CAPTURE_INTENT, e); if ((e.count 0) (e.data.u8[0] ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE)) { isStillCapture true; ATRACE_ASYNC_BEGIN(still capture, mNextRequests[i].halRequest.frame_number); } e camera_metadata_ro_entry_t(); find_camera_metadata_ro_entry(settings, ANDROID_CONTROL_ENABLE_ZSL, e); if ((e.count 0) (e.data.u8[0] ANDROID_CONTROL_ENABLE_ZSL_TRUE)) { isZslCapture true; } // 将这个request插入到mInFlightMap中 res parent-registerInFlight(halRequest-frame_number, totalNumBuffers, captureRequest-mResultExtras, /*hasInput*/halRequest-input_buffer ! NULL, hasCallback, expectedDurationInfo.minDuration, expectedDurationInfo.maxDuration, expectedDurationInfo.isFixedFps, requestedPhysicalCameras, isStillCapture, isZslCapture, captureRequest-mRotateAndCropAuto, captureRequest-mAutoframingAuto, mPrevCameraIdsWithZoom, passSurfaceMap ? uniqueSurfaceIdMap : SurfaceMap{}, captureRequest-mRequestTimeNs); } } return OK; }- sendRequestsBatch()流程待补充扩展一setRepeatingBurst和setRepeatingRequest的区别扩展二在setRepeatingRequest的过程中调用capture接口拍照会发生什么扩展三stopRepeating和abortCaptures的区别