OH-v3.0-LTS Camera相機(jī)驅(qū)動(dòng)框架(L2)解析3_創(chuàng)建流的準(zhǔn)備
原創(chuàng)??想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):??
??51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)??
??https://harmonyos.51cto.com??
1. 簡(jiǎn)單回顧
先簡(jiǎn)單回顧總結(jié)下前面兩章的內(nèi)容要點(diǎn)
- Camera HDI框架是通過(guò)綁定到HDF框架后在系統(tǒng)啟動(dòng)的時(shí)候完成初始化 Camera Host 實(shí)例。
- 應(yīng)用層通過(guò)獲取Camera Host 實(shí)例來(lái)得到設(shè)備支持的Camera的能力屬性,并Open相應(yīng)的設(shè)備。
- 應(yīng)用層通過(guò)IPC通訊來(lái)調(diào)用HDI接口
補(bǔ)充說(shuō)明
在前面CameraHostImpl::Init()創(chuàng)建CameraDevice實(shí)例對(duì)象的時(shí)候會(huì)實(shí)例化PipelineCore的各個(gè)子模塊包括HostStreamMgr、StreamPipelineCore對(duì)應(yīng)的功能會(huì)在下面的文章逐一說(shuō)明。
本章開(kāi)始略去IPC通訊相關(guān)的代碼(包括流程圖),讀者可以參考第一章中SetCallback流程自行梳理代碼。
2. 回到代碼
應(yīng)用層完成CameraDevice初始化后 開(kāi)始創(chuàng)建流 相關(guān)的上層調(diào)用代碼相對(duì)簡(jiǎn)單,這里簡(jiǎn)單畫(huà)個(gè)圖,大家可以對(duì)著代碼梳理下。我們從CreatStrem開(kāi)始繼續(xù)往下看。
先丟一個(gè)本章代碼涉及到的流程圖
2.1 Hos3516Demo::GetStreamOpt()
先為 流操作 接口創(chuàng)建一個(gè)上層回調(diào),然后通過(guò)IPC調(diào)用到CameraDeviceImpl的GetStreamOperator接口獲取流操作的實(shí)例。
//drivers\peripheral\camera\hal\init\3516_demo.cpp
void Hos3516Demo::GetStreamOpt()
{
int rc = 0;
if (streamOperator_ == nullptr) {
const sptr<IStreamOperatorCallback> streamOperatorCallback = new StreamOperatorCallback();
rc = demoCameraDevice_->GetStreamOperator(streamOperatorCallback, streamOperator_);
if (rc != Camera::NO_ERROR) {
CAMERA_LOGE("demo test: GetStreamOpt GetStreamOperator fail\n");
streamOperator_ = nullptr;
}
}
}
CameraDeviceImpl負(fù)責(zé)實(shí)例化StreamOperator對(duì)象,并調(diào)用StreamOperator::Init() 完成初始化。
//drivers\peripheral\camera\hal\hdi_impl\src\camera_device\camera_device_impl.cpp
CamRetCode CameraDeviceImpl::GetStreamOperator(
const OHOS::sptr<IStreamOperatorCallback> &callback,
OHOS::sptr<IStreamOperator> &streamOperator)
{
...
spCameraDeciceCallback_ = callback;
if (spStreamOperator_ == nullptr) {
spStreamOperator_ = new(std::nothrow) StreamOperator(spCameraDeciceCallback_, shared_from_this());
if (spStreamOperator_ == nullptr) {
CAMERA_LOGW("create stream operator failed.");
return DEVICE_ERROR;
}
spStreamOperator_->Init();
ismOperator_ = spStreamOperator_;
}
streamOperator = ismOperator_;
...
}
StreamOperator::Init() 會(huì)從前面實(shí)例化的CameraDevice對(duì)象中取出已經(jīng)實(shí)例化好的StreamPipelineCore對(duì)象調(diào)用對(duì)應(yīng)的Init初始化,同時(shí)創(chuàng)建一個(gè)進(jìn)程接收特定的消息。
//drivers\peripheral\camera\hal\hdi_impl\src\stream_operator\stream_operator.cpp
RetCode StreamOperator::Init()
{
...
pipelineCore_ = dev->GetPipelineCore();
...
streamPipeline_ = pipelineCore_->GetStreamPipelineCore();
...
RetCode rc = streamPipeline_->Init();
...
auto cb = [this](MessageGroup& m) { HandleCallbackMessage(m); };
messenger_ = std::make_shared<CaptureMessageOperator>(cb);
CHECK_IF_PTR_NULL_RETURN_VALUE(messenger_, RC_ERROR);
messenger_->StartProcess();
return RC_OK;
}
StreamPipelineCore::Init()繼續(xù)實(shí)例化StreamPipelineStrategy、StreamPipelineBuilder、StreamPipelineDispatcher 這3個(gè)類(lèi)。它們是負(fù)責(zé)pipeNode的創(chuàng)建和控制的,現(xiàn)在我們只要記得代碼已經(jīng)把它們實(shí)例化完成并放在了StreamPipelineCore里。
RetCode StreamPipelineCore::Init()
{
strategy_ = StreamPipelineStrategy::Create(context_->streamMgr_);
builder_ = StreamPipelineBuilder::Create(context_->streamMgr_);
dispatcher_ = StreamPipelineDispatcher::Create();
return RC_OK;
}
到這里StremOperator(下面紅框的部分)就創(chuàng)建好了,然后通過(guò)IPC回傳給上層應(yīng)用。
整個(gè)的StremOperator創(chuàng)建涉及到比較多的類(lèi) 對(duì)應(yīng)的關(guān)系可以看下下面的類(lèi)圖(個(gè)人理解,非官方)
2.2 Hos3516Demo::SetStreamInfo()
創(chuàng)建一個(gè)流信息 StreamInfo 這里的代碼相對(duì)簡(jiǎn)單,設(shè)置這個(gè)流的分辨率、編碼模式、流ID等等。
這里要注意的是bufferQueue_ 這個(gè)成員。下面會(huì)先簡(jiǎn)單講一下,算是挖個(gè)坑。
然后tunneledMode = 5這個(gè)地方感覺(jué)是個(gè)BUG 因?yàn)樵诤罄m(xù)的HDI代碼部分 實(shí)際是個(gè)bool類(lèi)型。
void Hos3516Demo::SetStreamInfo(std::shared_ptr<StreamInfo>& streamInfo,
const std::shared_ptr<StreamCustomer>& streamCustomer,
const int streamId, const StreamIntent intent)
{
constexpr uint32_t datasapce = 8;
constexpr uint32_t tunneledMode = 5;
if (intent == PREVIEW) {
constexpr uint32_t width = 640;
constexpr uint32_t height = 480;
streamInfo->width_ = width;
streamInfo->height_ = height;
} else if (intent == STILL_CAPTURE) {
constexpr uint32_t width = 1280;
constexpr uint32_t height = 960;
streamInfo->width_ = width;
streamInfo->height_ = height;
streamInfo->encodeType_ = ENCODE_TYPE_JPEG;
} else {
constexpr uint32_t width = 1280;
constexpr uint32_t height = 960;
streamInfo->width_ = width;
streamInfo->height_ = height;
streamInfo->encodeType_ = ENCODE_TYPE_H265;
}
streamInfo->streamId_ = streamId;
streamInfo->format_ = PIXEL_FMT_YCRCB_420_SP;
streamInfo->datasapce_ = datasapce;
streamInfo->intent_ = intent;
streamInfo->tunneledMode_ = tunneledMode;
streamInfo->bufferQueue_ = streamCustomer->CreateProducer();
streamInfo->bufferQueue_->SetQueueSize(8); // 8:set bufferQueue size
}
StreamCustomer::CreateProducer()
這里的OHOS::Surface 涉及到了Graphic子系統(tǒng)中的Surface。Surface 是圖形緩沖區(qū)管理接口,負(fù)責(zé)管理圖形緩沖區(qū)和高效便捷的輪轉(zhuǎn)緩沖區(qū)。
詳細(xì)的說(shuō)明可以看下源碼中的Readme路徑在:foundation/graphic/standard/README_zh.md。
是這里按照我個(gè)人的理解先簡(jiǎn)單的說(shuō)一下:
Surface分成了一個(gè)“生產(chǎn)者” 一個(gè) “消費(fèi)者”。應(yīng)用端作為“消費(fèi)者”向Surface模塊申請(qǐng)一個(gè)Surface。當(dāng)對(duì)應(yīng)的“生產(chǎn)者”產(chǎn)生了數(shù)據(jù)就會(huì)通知“消費(fèi)者” 對(duì)數(shù)據(jù)進(jìn)行處理。
StreamCustomer::CreateProducer()做了兩件事情
- 為上層應(yīng)用獲取了一個(gè)“消費(fèi)型”surface
- 從獲取到的surface中取出對(duì)應(yīng)的“生產(chǎn)者”對(duì)象放在了StremInfo的信息里 丟給StreamOperator
//drivers\peripheral\camera\hal\init\stream_customer.cpp
sptr<OHOS::IBufferProducer> StreamCustomer::CreateProducer()
{
consumer_ = OHOS::Surface::CreateSurfaceAsConsumer(); //Buffer的消費(fèi)者來(lái)使用該函數(shù)創(chuàng)建一個(gè)Surface
if (consumer_ == nullptr) {
return nullptr;
}
sptr<IBufferConsumerListener> listener = new TestBuffersConsumerListener();
consumer_->RegisterConsumerListener(listener); //注冊(cè)一個(gè)消費(fèi)監(jiān)聽(tīng)器,監(jiān)聽(tīng)Buffer的Flush事件
auto producer = consumer_->GetProducer(); //獲得一個(gè)Surface內(nèi)部的IBufferProducer對(duì)象
if (producer == nullptr) {
return nullptr;
}
CAMERA_LOGI("demo test, create a buffer queue producer %{public}p", producer.GetRefPtr());
return producer;
}
3. 小結(jié)
代碼到這邊 上層應(yīng)用已經(jīng)獲取到了HDI層的StreamOperator對(duì)象實(shí)例。同時(shí)為圖像數(shù)據(jù)準(zhǔn)備了一個(gè)Surface!
同樣挖了兩個(gè)小坑,留待后面的代碼進(jìn)一步講解
- StreamPipelineStrategy、StreamPipelineBuilder、StreamPipelineDispatcher 這些類(lèi)是怎么工作的?
- Surface的“生產(chǎn)者”在哪里?
??想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):??
??51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)??
??https://harmonyos.51cto.com??