ue操作
上述步骤2主要是将每一个Stream下全部的buffer信息全部register到下层的HAL3中,为后续对buffer的数据流读写操作奠定基础。
那么preview模式下我们又是如何去获得一帧完成的视频流的呢?
触发点就是preview模式下的Request,前面提到过一个mPreviewRequest至少包含一个StreamProcessor和一个CallbackProcessor的两路stream,每路stream拥有不同的buffer数量。比如要从HAL3获取一帧图像数据,最简单的思路就是从StreamProcessor下的Outputstream流中下发一个可用的buffer地址,然后HAL3填充下数据,Framework就可以拥有一帧数据了。
根据这个思路,回顾到前一博文中每次会不断的下发一个Request命令包到HAL3中,在这里我们就可以看到这个buffer地址身影。
Camera3Device::RequestThread::threadLoop() 下的部分代码:
outputBuffers.insertAt(camera3_stream_buffer_t(), 0,
nextRequest->mOutputStreams.size());//Streamprocess,Callbackprocessor
request.output_buffers = outputBuffers.array();//camera3_stream_buffer_t
for (size_t i = 0; i < nextRequest->mOutputStreams.size(); i++) {
res = nextRequest->mOutputStreams.editItemAt(i)->
getBuffer(&outputBuffers.editItemAt(i));//等待获取buffer,内部是dequeue一根buffer填充到camera3_stream_buffer_t
if (res != OK) {
// Can't get output buffer from gralloc queue - this could be due to
// abandoned queue or other consumer misbehavior, so not a fatal
// error
ALOGE(RequestThread: Can't get output buffer, skipping request:
%s (%d), strerror(-res), res);
Mutex::Autolock l(mRequestLock);
if (mListener != NULL) {
mListener->notifyError(
ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
nextRequest->mResultExtras);
}
cleanUpFailedRequest(request, nextRequest, outputBuffers);
return true;
}
request.num_output_buffers++;//一般一根OutStream对应一个buffer,故总的out_buffer数目
}
在这个下发到HAL3的camera3_capture_request中,可以看到 const camera3_stream_buffer_t *output_buffers,下面的代码可以说明这一次的Request的output_buffers是打包了当前Camera3Device所拥有的mOutputStreams。
outputBuffers.insertAt(camera3_stream_buffer_t(), 0,
nextRequest->mOutputStreams.size());//Streamprocess,Callbackprocessor
对于每一个OutputStream他会给她分配一个buffer handle。关注下面的处理代码:
nextRequest->mOutputStreams.editItemAt(i)->
getBuffer(&outputBuffers.editItemAt(i))
nextRequest->mOutputStreams.editItemAt(i)是获取一个Camera3OutputStream对象,然后对getBuffer而言传入的是这个Camera3OutputStream所对应的这次buffer的输入位置,这个camera3_stream_buffer是需要从Camera3OutputStream对象中去获取的。
status_t Camera3Stream::getBuffer(camera3_stream_buffer *buffer) {
ATRACE_CALL();
Mutex::Autolock l(mLock);
status_t res = OK;
// This function should be only called when the stream is configured already.
if (mState != STATE_CONFIGURED) {
ALOGE(%s: Stream %d: Can't get buffers if stream is not in CONFIGURED state %d,
__FUNCTION__, mId, mState);
return INVALID_OPERATION;
}
// Wait for new buffer returned back if we are running into the limit.
if (getHandoutOutputBufferCountLocked() == camera3_stream::max_buffers) {//dequeue过多时等待queue的释放
ALOGV(%s: Already dequeued max output buffers (%d), wait for next returned one.,
__FUNCTION__, camera3_stream::max_buffers);
res = mOutputBufferReturnedSignal.waitRelative(mLock, kWaitForBufferDuration);
if (res != OK) {
if (res == TIMED_OUT) {
ALOGE(%s: wait for output buffer return timed out after %lldms, __FUNCTION__,
kWaitForBufferDuration / 1000000LL);
}
return res;
}
}
res = getBufferLocked(buffer);
if (res == OK) {
fireBufferListenersLocked(*buffer, /*acquired*/true, /*output*/true);
}
return res;
}
上述的代码先是检查dequeue了的buffe