文章目录
0. Camera简单结构
1. CameraService模块启动流程
CameraService是NativeService, 所以随着init启动并加入到Native ServiceManager中。
1.5 Camera连接流程
openCamera说明:
- openCamera实质上是创建客户端(CameraDevice)和服务端的通信渠道,而CameraManager是操作入口。
- CameraDevice在创建的过程中,会打开并初始化Camera设备。
- APP后续的操作基本都是基于CameraDevice的接口在和服务端通信。
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
的接口
开始预览流程