Android(安卓)9.0 Camera学习笔记
16lz
2021-01-26
文章目录
- 1. CameraService模块启动流程
- 2. 相机startPreview流程图
- - Camera的请求和响应处理流程
- - repeating原理:
- - 注意
- 3. Camera2 录像流程图
- 4. Camera2 API_2 从CameraActivity初始化到Camera preview的流程
- 5. Camera2 takePicture代码流程
1. CameraService模块启动流程
CameraService是NativeService, 所以随着init启动并加入到Native ServiceManager中。
2. 相机startPreview流程图
- Camera的请求和响应处理流程
Camera FW和HAL3的请求和响应,还有数据交互都是基于Stream的(Camera3InputStream,Camera3OutputStream)
请求分为三大类:
- Preview(预览)
- Capture(拍照)
- Recording(录像)
流程:
- Camera2Client 发起预览/拍照/录像请求;
- 创建(Preview/Capture/Recording)OutputStream(mSurface), 返回对应的streamId, 并记录在对应的Processor中;
- 创建(Preview/Capture/Recording)Request;
- 将需要请求数据的outputstream添加到request中;
- 初始化Request, 并最终加入到Request列表中;
- 在Camera3Device的threadLoop中处理所有的Request请求;
- 处理请求前, 从每个ouputstream中保存的surfaceProducer各自申请一块buffer(dequeueBuffer);
- 将buffer携带到request中, 然后发送携带了请求包含的所有outputstreams和每个stream对应的buffer到HAL3;
- HAL3收到并处理请求, 然后会填充camera获取的图象数据到携带的buffer, 并填充结果信息,并返回给Camera FW.
- Camera FW收到返回的内容之后, 获取到填充了图像信息的buffer和outputstream;
- 遍历所有outputStreams(请求时带给HAL的outputstreams),获取到每个outputstream中的surfaceProducer, 通过surfaceProducer将获取的buffer queueBuffer到图形队列BufferQueue中, 交给Consumer来处理;
- repeating原理:
Camera3Device::RequestThread::waitForNextRequestBatch()
void Camera3Device::RequestThread::waitForNextRequestBatch() { ATRACE_CALL(); // Optimized a bit for the simple steady-state case (single repeating // request), to avoid putting that request in the queue temporarily. Mutex::Autolock l(mRequestLock); assert(mNextRequests.empty()); NextRequest nextRequest; //获取下一个请求(先只获取一个) nextRequest.captureRequest = waitForNextRequestLocked(); if (nextRequest.captureRequest == nullptr) { //请求队列和repeating类型的请求都没有 return; } nextRequest.halRequest = camera3_capture_request_t(); nextRequest.submitted = false; mNextRequests.add(nextRequest); // Wait for additional requests //当前要是支持批量请求的发送方式,则继续获取下一个请求 //(注意:repeatingRequest最多只会获取一个,当队列不为空时, 将不会再获取 //repeating请求,所以上面已经有一个请求(不管是不是repeating请求),这类都不会再获 //取repeating请求, 二十从队列中获取其他类型的请求, 比如capture) const size_t batchSize = nextRequest.captureRequest->mBatchSize;//获取到camera HAL设备支持的最大批量数量的请求。 for (size_t i = 1; i < batchSize; i++) { NextRequest additionalRequest; additionalRequest.captureRequest = waitForNextRequestLocked(); if (additionalRequest.captureRequest == nullptr) { break; } additionalRequest.halRequest = camera3_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;}sp<Camera3Device::CaptureRequest> Camera3Device::RequestThread::waitForNextRequestLocked() { status_t res; sp<CaptureRequest> nextRequest;//注意 这里当队列为空的时候,才回去尝试获取repeating请求,获取不到说明//当前没有任何请求可以获取,则阻塞等待; while (mRequestQueue.empty()) { if (!mRepeatingRequests.empty()) { //请求队列为空,但是mRepeatingRequests不为空,尝试获取repeating request; // Always atomically enqueue all requests in a repeating request // list. Guarantees a complete in-sequence set of captures to // application. const RequestList &requests = mRepeatingRequests; RequestList::const_iterator firstRequest = requests.begin();//获取一个repeating request; nextRequest = *firstRequest; //插入到请求队列中 mRequestQueue.insert(mRequestQueue.end(), ++firstRequest, requests.end()); // No need to wait any longer mRepeatingLastFrameNumber = mFrameNumber + requests.size() - 1; //获取到请求之后, 跳出 break; }//没有获取到任何请求, 阻塞等待新的请求到来; res = mRequestSignal.waitRelative(mRequestLock, kRequestTimeout); if ((mRequestQueue.empty() && mRepeatingRequests.empty()) || exitPending()) { Mutex::Autolock pl(mPauseLock); if (mPaused == false) { ALOGV("%s: RequestThread: Going idle", __FUNCTION__); mPaused = true; // Let the tracker know sp<StatusTracker> statusTracker = mStatusTracker.promote(); if (statusTracker != 0) { statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE); } } // Stop waiting for now and let thread management happen return NULL; } } if (nextRequest == NULL) { //没有获取到repeating请求 // Don't have a repeating request already in hand, so queue // must have an entry now. //从请求队列中获取新的请求 RequestList::iterator firstRequest = mRequestQueue.begin(); nextRequest = *firstRequest; mRequestQueue.erase(firstRequest); if (mRequestQueue.empty() && !nextRequest->mRepeating) { sp<NotificationListener> listener = mListener.promote(); if (listener != NULL) { listener->notifyRequestQueueEmpty(); } } } // In case we've been unpaused by setPaused clearing mDoPause, need to // update internal pause state (capture/setRepeatingRequest unpause // directly). Mutex::Autolock pl(mPauseLock); if (mPaused) { ALOGV("%s: RequestThread: Unpaused", __FUNCTION__); sp<StatusTracker> statusTracker = mStatusTracker.promote(); if (statusTracker != 0) { statusTracker->markComponentActive(mStatusId); } } mPaused = false; // Check if we've reconfigured since last time, and reset the preview // request if so. Can't use 'NULL request == repeat' across configure calls. if (mReconfigured) { mPrevRequest.clear(); mReconfigured = false; } if (nextRequest != NULL) { nextRequest->mResultExtras.frameNumber = mFrameNumber++; nextRequest->mResultExtras.afTriggerId = mCurrentAfTriggerId; nextRequest->mResultExtras.precaptureTriggerId = mCurrentPreCaptureTriggerId; // Since RequestThread::clear() removes buffers from the input stream, // get the right buffer here before unlocking mRequestLock if (nextRequest->mInputStream != NULL) { res = nextRequest->mInputStream->getInputBuffer(&nextRequest->mInputBuffer); if (res != OK) { // Can't get input buffer from gralloc queue - this could be due to // disconnected queue or other producer misbehavior, so not a fatal // error ALOGE("%s: Can't get input buffer, skipping request:" " %s (%d)", __FUNCTION__, strerror(-res), res); sp<NotificationListener> listener = mListener.promote(); if (listener != NULL) { listener->notifyError( hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST, nextRequest->mResultExtras); } return NULL; } } } return nextRequest; //最后返回获取到的请求}
- 注意
- CallbackProcessor和JpegProcessor 的Consumer是CpuConsumer, 注册的FrameAvailableListener是自己, 所以queueBuffer之后, 回调响应是自己的onFrameAvailable函数。
- CpuConsumer的lockNextBuffer(&buffer)可以获取到来自produser queue的buffer.
-
- JpegProcessor 收到的图象buffer最终在CaptureSequencer中处理.
-
- CaptureSequencer是一个状态机模型, 每个状态函数的返回值代表了要转移的状态.
- 最终完成拍照数据获取,是在CaptureSequencer::manageDone函数.
3. Camera2 录像流程图
Camera2 的录像使用的是Camera2 API_1
的接口
4. Camera2 API_2 从CameraActivity初始化到Camera preview的流程
Camera2 preview流程使用的是Camera2 API_2
的接口
开始预览流程
5. Camera2 takePicture代码流程
更多相关文章
- android 如何定义全局变量
- Android(安卓)studio 设计简易的计算器
- [转]Android(安卓)获取当前Activity的屏幕截图
- 获取 Andorid 手机WIFI连接的Mac地址和IP地址
- 使用git工具获取android源代码
- android点击任意非EditText区域,隐藏键盘
- Android获取assets目录下的文件和图片
- OkHttp得拦截机制
- delphixe10 android操作 打电话,摄像头,定位等