写到第五篇,我们已经把大致的流程已经贯穿完了,还有很多东西没有讲,日后慢慢再说。不过现在有一个重要的问题,就是整个流利里各种buf,provider,bufmgr,queue类等之间的关系,说白了就是buf类和buf辅助类之前的关系。理清这些类的关系和这些类的作用,再从Buf流理解一下整个框架,CamAdapter和CamClient是怎么通过Buf联系,会对日后的分析有一个很大的帮助。也相当于对本文的一个总结。本来为了避免贴太多代码,想直接写中文总结的,后来发现贴代码虽然看得更辛苦一点,但细节更清晰,还是贴代码吧
DisplayClient::onThreadLoop(Command const& rCmd)
{
// (0) lock Processor.
//pImgBufQueue的实现在ImgBufQueue.cpp里
sp<IImgBufQueue> pImgBufQueue;
pImgBufQueue = mpImgBufQueue;
/** (1) Prepare all TODO buffers.
pImgBufQueue里有两个Buf队列mTodoImgBufQue和mDoneImgBufQue
下面的函数用StreamImgBuf生成好ImgBufQueNode,把buf的标志位设为eSTATUS_TODO
后调用ImgBufQueue的enqueProcessor()把所有的Buf都放入到mTodoImgBufQue做接收数据的准备
**/
prepareAllTodoBuffers(pImgBufQueue);
// (2) Start 只是通知队列,不做任何队列的数据处理
pImgBufQueue->startProcessor();
// (3) Do until disabled.
while ( 1 )
{
/**(.1) 在此处会ImgBufQueue的dequeProcessor()等待通知,并接收数据
收到通知后,接收的是mDoneImgBufQue,一个ImgBufQueNode队列
接收到队列后把整个mDoneImgBufQue传入handleReturnBuffers()中被处理
handleReturnBuffers()首先会获得单个ImgBufQueNode中的IImgBuf,即最原始的Mem
接下来就是操作mem。中途还有一些逻辑和StreamImgBuf有关联,现在忽略
**/
waitAndHandleReturnBuffers(pImgBufQueue);
// (.2) break if disabled.
if ( ! isDisplayEnabled() )
{
MY_LOGI("Display disabled");
break;
}
//又把buf放加到mTodoImgBufQue
prepareAllTodoBuffers(pImgBufQueue);
}
//
// (4) Stop
//退出,并清除队列,把BufQueNode标志位设为eSTATUS_CANCEL
pImgBufQueue->pauseProcessor();
pImgBufQueue->flushProcessor();
pImgBufQueue->stopProcessor();
}
看到这里我们了解到了 ImgBufQueNode为基本buf,里面包装了一个IImgBuf,用于操作内存存储 ImgBufQueue继承于IImgBufQueue和IImgBufProvider,是一个
ImgBufQueNode队列的管理器,里面包含两条buf队列,
一个是mTodoImgBufQue
,一个是
mDoneImgBufQue
,里面
装载着两种不同状态的buf,会把闲置的buf放入todo里,装好数据的buf装到done里,等待处理。在
ImgBufQueue里有两个系列的函数
Process系列:
virtual bool enqueProcessor(ImgBufQueNode const& rNode) = 0;
virtual bool dequeProcessor(Vector<ImgBufQueNode>& rvNode) = 0;
//
virtual bool startProcessor() = 0;
virtual bool pauseProcessor() = 0;
virtual bool flushProcessor() = 0;
virtual bool stopProcessor() = 0;
Provider系列
virtual bool dequeProvider(ImgBufQueNode& rNode) = 0;
virtual bool enqueProvider(ImgBufQueNode const& rNode) = 0;
virtual bool queryProvider(ImgBufQueNode& rNode) = 0;
这些系统函数都继承于他们的父类,其中Process系列的我们已经都看到了,只要给DisplayClient内部用于负责操作mTodoImgBufQue和mDoneImgBufQue的数据进出。但我们根据立面的分析知道,DisplayClient的数据由外部的CamAdapter提供,接下来就从CamAdapter角度来分析:
/**
CamAdapter继承了IImgBufProviderClient。并实现了onImgBufProviderCreated()函数
DisplayClient的setImgBufProviderClient(),传入了一个CamAdapter,即IImgBufProviderClient
并调用CamAdapter的onImgBufProviderCreated,传入参数是ImgBufQueue。即IImgBufProvider
**/
BaseCamAdapter::onImgBufProviderCreated(sp<IImgBufProvider>const& rpProvider)
{
int32_t const i4ProviderId = rpProvider->getProviderId();
//把ImgBufQueue放入ImgBufProvidersManager
//此时ImgBufProvidersManager就拥有了DisplayClient和CamClient的数据队列ImgBufQueue
mpImgBufProvidersMgr->setProvider(i4ProviderId, rpProvider);
}
/**
我们直接跑到PreviewCmdQueThread的UpdateOne(),在此函数里,从Sensor接收并处理完数据后
会把Buf传给mspPreviewBufHandler
**/
PreviewCmdQueThread::updateOne()
{
//从DisplayClient的ImgBufQueue的mTodoImgBufQue取出Buf
mspPreviewBufHandler->dequeBuffer(eID_Pass2DISPO, dispNode);
//mspPreviewBufHandler的实现是PreviewBufMgr,PreviewBufMgr的继承关系是
//PreviewBufMgr-->IPreviewBufMgr-->IPreviewBufMgrHandler
dispNode.getImgBuf()->setTimestamp(pass1LatestTimeStamp);
//把Buf放到DisplayClient的ImgBufQueue的mDoneImgBufQue
mspPreviewBufHandler->enqueBuffer(dispNode);
}
PreviewBufMgr::enqueBuffer(ImgBufQueNode const& node)
{
// (2) choose the correct "client"
switch (node.getCookieDE())
{
case eBuf_Pass1:
//...
case eBuf_Disp:
{
//从ImgBufProvidersManager找出Provider,这里即我们的DisplayClient的ImgBufQueue
sp<IImgBufProvider> bufProvider = mspImgBufProvidersMgr->getDisplayPvdr();
if (bufProvider != 0)
{
//调用DisplayClient的ImgBufQueue
bufProvider->enqueProvider(node);
}
}
break;
//
case eBuf_AP:
//...
case eBuf_FD:
//...
case eBuf_Rec:
//...
}
}
//DisplayClitn的ImgBufQueue
ImgBufQueue::enqueProvider(ImgBufQueNode const& rNode)
{
mDoneImgBufQue.push_back(rNode);
mDoneImgBufQueCond.broadcast();
}
看到这里我们又知道了:
IImgBufProviderClient是用来管理IImgBufProvider,即让CamAdapter通过ImgBufProvidersManager管理DisplayClient的IImgBufProvider
这里的IImgBufProvider是我们DiaplayClient数据队列的管理者ImgBufQueue的父类。管理着mTodoImgBufQue和mDoneImgBufQue
上面说了ImgBufQueue继承了Provider和Process,并实现了他们的函数,其中Provider是提供给外部的类提出数据包和插入数据包,而Process是用来给内部整理和读取数据包。就如我们的DisplayClient的ImgBufQueue,DisplayClient内部生成和读取Buf通过Process系列函数,而DisplayClient把Provider系列函数提供给了CamAdapter操作数据包
这里还涉及了两个外部管理类,ImgBufProvidersManager和PreviewBufMgr,他们的继承关系是:
ImgBufProvidersManager–>RefBase
PreviewBufMgr–>IPreviewBufMgr–>IPreviewBufMgrHandler
ImgBufProvidersManager是用来管理ImgBufQueue,DisplayClient和CamClient都在它的管理内
PreviewBufMgr则是提取Provider的数据包,并填充数据再按数据包的作用通过ImgBufProvidersManager找到相应的Provider,把数据传给Provider