OpenHarmony camera người dùng thái điều khiển dàn giáo Nguyên sangTinh hoa
Tác giả: Nhuận cùng phần mềm quách tân tinh
Camera làm smart phone thượng ít có trưởng thành không gian không tồi, có thể làm ra sai biệt hóa công năng, mỗi năm đều có thể trở thành các đại Android di động nhà máy hiệu buôn tranh nhau tuyên truyền lượng điểm. Mọi người đều biết Android chọn dùng Linux làm này nội hạch, mà Linux chọn dùng khai nguyên hiệp nghị có lây bệnh tính [^1], dẫn tới Android HAL[^2] trở thành di động nhà máy hiệu buôn nhóm cạnh tranh quan trọng chiến trường. Theo OpenHarmony 3.1[^3] tuyên bố, camera mô khối cũng dần dần hoàn thiện lên, trước mắt cung cấp cơ sở xem trước cùng chụp ảnh năng lực. OpenHarmony trung, camera người dùng thái điều khiển dàn giáo gánh vác cùng Android Camera HAL giống nhau nhân vật, này bộ phận ở vào OpenHarmony HDF[^4] trung, đối thượng thực hiện camera HDI[^5] tiếp lời, đối hạ thực hiện camera Pipeline mô hình, quản lý camera các phần cứng thiết bị.
Camera người dùng thái điều khiển dàn giáo ( hạ đồ CameraHost bộ phận ) tổng thể có thể chia làm ba tầng, HDI thực hiện tầng, thực hiện camera tiêu chuẩn nam hướng tiếp lời; dàn giáo tầng, nối tiếp HDI thực hiện tầng khống chế, lưu chuyển phát, thực hiện số liệu thông lộ dựng, quản lý camera các phần cứng thiết bị chờ công năng; thích xứng tầng, che chắn tầng dưới chót chip cùng OS sai biệt, duy trì nhiều ngôi cao thích xứng.
• mô khối giới thiệu
HDI Implementation: Đối thượng thực hiện HDI tiếp lời, xuống phía dưới thuyên chuyển dàn giáo tầng tiếp lời, hoàn thành HDI tiếp lời nhiệm vụ chuyển phát.
Buffer Manager: Che chắn bất đồng nội tồn quản lý sai biệt, vì tử hệ thống cung cấp thống nhất thao tác tiếp lời, đồng thời cung cấp buffer luân chuyển công năng.
Pipeline Core: Phân tích HCS phối trí hoàn thành pipeline dựng, điều hành pipeline trung các node hoàn thành lưu xử lý
Device Manager: Thông qua thuyên chuyển tầng dưới chót phần cứng thích xứng tầng tiếp lời, thực hiện tuần tra khống chế tầng dưới chót thiết bị, cái cử nghe lén tầng dưới chót thiết bị công năng
Platform Adaption: Che chắn phần cứng sai biệt, vì Device Manager cung cấp thống nhất thao tác tầng dưới chót phần cứng năng lực
• mục lục kết cấu
Shell
drivers/peripheral/camera
|-- README_zh.md
|-- bundle.json
|-- figures
| `-- logic-view-of-modules-related-to-this-repository_zh.png
|-- hal
| |-- BUILD.gn
| |-- adapter
| |-- buffer_manager
| |-- camera.gni
| |-- device_manager
| |-- hdi_impl
| |-- include
| |-- init
| |-- pipeline_core
| |-- test
| `-- utils
|-- hal_c
| |-- BUILD.gn
| |-- camera.gni
| |-- hdi_cif
| `-- include
`-- interfaces
|-- hdi_ipc
|-- hdi_passthrough
`-- include
•HDI Implementation trung xem trước lưu trình
Kế tiếp chúng ta thông qua đã tuyên bố OpenHarmony 3.1 khai nguyên số hiệu, đến xem xem trước là như thế nào hoàn thành đi
drivers/peripheral/camera/hal/test/v4l2/src /preview_test.cpp gửi nhằm vào v4l2 xem trước thí nghiệm số hiệu, nhập khẩu như sau
C++
TEST_F(UtestPreviewTest, camera_preview_0001)
{
std::cout << "==========[test log] Preview stream, expected success." << std::endl;
// Get the stream manager
display_->AchieveStreamOperator(); // thu hoạch stream operator
// start stream
display_->intents = {Camera::PREVIEW}; // xem trước lưu
display_->StartStream(display_->intents); // khởi lưu
// Get preview
display_->StartCapture(display_->streamId_preview, display_->captureId_preview, false, true);
// release stream
display_->captureIds = {display_->captureId_preview};
display_->streamIds = {display_->streamId_preview};
display_->StopStream(display_->captureIds, display_->streamIds);
}
Trước thu hoạch stream operator ví dụ thực tế
C++
void testdisplay::achievestreamoperator()
{
// create and get streamoperator information
std::shared_ptr<ohos::camera::istreamoperatorcallback> streamoperatorcallback =
std::make_shared<ohos::camera::istreamoperatorcallback>();
rc = cameradevice->getstreamoperator(streamoperatorcallback, streamoperator);
//........
}
Thông qua trước văn streamOperator sáng tạo lưu
C++
void TestDisplay::StartStream(std::vector<OHOS::Camera::StreamIntent> intents)
{
//..............................
for (auto& intent: intents) {
if (intent == 0) {
std::shared_ptr<IBufferProducer> producer = IBufferProducer::CreateBufferQueue();
producer->SetQueueSize(8); // sáng tạo buffer sinh sản đoan, cũng cùng tương ứng chảy vào hành trói định
auto callback = [this](std::shared_ptr<SurfaceBuffer> Prebuffer) {
BufferCallback(Prebuffer, preview_mode);
return;
};
producer->SetCallback(callback);
streamInfo->streamId_ = streamId_preview;
streamInfo->width_ = 640; // 640:picture width
streamInfo->height_ = 480; // 480:picture height
streamInfo->format_ = CAMERA_FORMAT_YUYV_422_PKG;
streamInfo->datasapce_ = 8; // 8:picture datasapce
streamInfo->intent_ = intent;
streamInfo->tunneledMode_ = 5; // 5:tunnel mode
streamInfo->bufferQueue_ = producer;
streamInfos.push_back(streamInfo);
} else if (intent == 1) {
//.......................
}
rc = streamOperator->CreateStreams(streamInfos); // sáng tạo lưu
//................................
rc = streamOperator->CommitStreams(Camera::NORMAL, ability); // đệ trình lưu
//.................................
}
Phía dưới chúng ta chính thức tiến vào đến hal nguyên số hiệu nhìn xem là như thế nào sáng tạo lưu đi
C++
CamRetCode StreamOperator::CreateStreams(const std::vector<std::shared_ptr<StreamInfo>>& streamInfos)
{
//.....
for (auto it: streamInfos) {
//....
std::shared_ptr<IStream> stream = StreamFactory::Instance().CreateShared(
IStream::g_availableStreamType[it->intent_], it->streamId_, it->intent_, pipelineCore_, messenger_); // sáng tạo lưu ví dụ thực tế
//...
StreamConfiguration scg;
scg.id = it->streamId_;
scg.type = it->intent_;
scg.width = it->width_;
scg.height = it->height_;
PixelFormat pf = static_cast<PixelFormat>(it->format_);
scg.format = BufferAdapter::PixelFormatToCameraFormat(pf);
scg.dataspace = it->datasapce_;
scg.tunnelMode = it->tunneledMode_;
scg.minFrameDuration = it->minFrameDuration_;
scg.encodeType = it->encodeType_;
RetCode rc = stream->ConfigStream(scg); // căn cứ câu trên lưu tin tức phối trí lưu
//...
if (it->bufferQueue_!= nullptr) { // trói định trước văn sinh sản đoan
auto tunnel = std::make_shared<StreamTunnel>();
CHECK_IF_PTR_NULL_RETURN_VALUE(tunnel, INSUFFICIENT_RESOURCES);
RetCode rc = tunnel->AttachBufferQueue(it->bufferQueue_);
CHECK_IF_NOT_EQUAL_RETURN_VALUE(rc, RC_OK, INVALID_ARGUMENT);
if (stream->AttachStreamTunnel(tunnel)!= RC_OK) {
CAMERA_LOGE( "attach buffer queue to stream [id = %{public}d] failed", it->streamId_);
return INVALID_ARGUMENT;
}
}
{
std::lock_guard<std::mutex> l(streamLock_);
streamMap_[stream->GetStreamId()] = stream; // bảo tồn lưu ví dụ thực tế
}
//...
}
Từ phía trên có thể thấy được, tiêu phí đoan truyền lại tới rồi hal, kia tất nhiên là từ hal từ bufferproducer thu hoạch buffer, cũng kích phát xem trước khởi động lưu trình. Kia nhìn xem AttachStreamTunnel thực hiện đi
C++
RetCode StreamBase::AttachStreamTunnel(std::shared_ptr<StreamTunnel>& tunnel)
{
if (state_ == STREAM_STATE_BUSY || state_ == STREAM_STATE_OFFLINE) {
return RC_ERROR;
}
tunnel_ = tunnel; // trói định sinh sản đoan
CHECK_IF_PTR_NULL_RETURN_VALUE(tunnel_, RC_ERROR);
tunnel_->SetBufferCount(GetBufferCount()); // phối trí luân chuyển buffer cái số
TunnelConfig config = {(uint32_t)streamConfig_.width, (uint32_t)streamConfig_.height,
(uint32_t)streamConfig_.format, streamConfig_.usage};
tunnel_->Config(config);
streamConfig_.tunnelMode = true;
return RC_OK;
}
CreateStream lúc sau đó là CommitStream, nơi này CommitStream làm chút sự tình gì đâu, chúng ta tiếp theo đi xuống xem
C++
CamRetCode StreamOperator::CommitStreams(OperationMode mode,
const std::shared_ptr<CameraStandard::CameraMetadata>& modeSetting)
{
//......
std::vector<StreamConfiguration> configs = {};
{
std::lock_guard<std::mutex> l(streamLock_);
for (auto it: streamMap_) { // thu hoạch lưu phối trí, trước văn CreateStrea khi bảo tồn lưu
configs.emplace_back(it.second->GetStreamAttribute());
}
}
// kiểm tra lưu hay không bị duy trì
DynamicStreamSwitchMode method = streamPipeline_->CheckStreamsSupported(mode, modeSetting, configs);
if (method == DYNAMIC_STREAM_SWITCH_NOT_SUPPORT) {
return INVALID_ARGUMENT;
}
if (method == DYNAMIC_STREAM_SWITCH_NEED_INNER_RESTART) {
std::lock_guard<std::mutex> l(streamLock_);
for (auto it: streamMap_) {
it.second->StopStream();// nếu lưu bị duy trì, nhưng yêu cầu bên trong khởi động lại, nơi này trước đình lưu
}
}
{
std::lock_guard<std::mutex> l(streamLock_);
for (auto it: streamMap_) {
if (it.second->CommitStream()!= RC_OK) { // chân chính CommitStream, phía dưới lại nói tỉ mỉ
CAMERA_LOGE( "commit stream [id = %{public}d] failed.", it.first);
return DEVICE_ERROR;
}
}
}
RetCode rc = streamPipeline_->PreConfig(modeSetting); // đem hình thức truyền vào tiến hành dự phối trí
if (rc!= RC_OK) {
CAMERA_LOGE( "prepare mode settings failed" );
return DEVICE_ERROR;
}
rc = streamPipeline_->CreatePipeline(mode);// sáng tạo pipeline
if (rc!= RC_OK) {
CAMERA_LOGE( "create pipeline failed." );
return INVALID_ARGUMENT;
}
DFX_LOCAL_HITRACE_END;
return NO_ERROR;
}
C++
RetCode StreamBase::CommitStream()
{
//...
hostStreamMgr_ = pipelineCore_->GetHostStreamMgr(); // từ pipelinecore thu hoạch hoststreamanager
CHECK_IF_PTR_NULL_RETURN_VALUE(hostStreamMgr_, RC_ERROR);
//...
info.bufferPoolId_ = poolId_;
info.bufferCount_ = GetBufferCount();
// khởi động lại bufferpool
RetCode rc = bufferPool_->Init(streamConfig_.width, streamConfig_.height, streamConfig_.usage,
streamConfig_.format, GetBufferCount(), CAMERA_BUFFER_SOURCE_TYPE_EXTERNAL);
if (rc!= RC_OK) {
CAMERA_LOGE( "stream [id:%{public}d] initialize buffer pool failed.", streamId_);
return RC_ERROR;
}
}
// stream truyền lại đến pipelinecore cũng tiến hành trói định
RetCode rc = hostStreamMgr_->CreateHostStream(info, [this](std::shared_ptr<IBuffer> buffer) {
HandleResult(buffer);
return;
});
//....
return RC_OK;
}
CreateStream cùng CommitStream sau khi chấm dứt đó là Capture, nơi này bao hàm khởi lưu động tác, mấu chốt thực hiện như sau
C++
CamRetCode StreamOperator::Capture(int captureId, const std::shared_ptr<CaptureInfo>& captureInfo, bool isStreaming)
{
//...
// captureId bắt được thỉnh cầu id; captureInfo xem trước / chụp ảnh / ghi hình tham số; isStreaming liên tục bắt được vẫn là đơn thứ bắt được ( chụp ảnh )
CaptureSetting setting = captureInfo->captureSetting_;
auto request =
std::make_shared<CaptureRequest>(captureId, captureInfo->streamIds_.size(), setting,
captureInfo->enableShutterCallback_, isStreaming);
for (auto id: captureInfo->streamIds_) {
// sáng tạo bắt được thỉnh cầu, cũng truyền lại cấp trước văn sáng tạo lưu
RetCode rc = streamMap_[id]->AddRequest(request);
if (rc!= RC_OK) {
return DEVICE_ERROR;
}
}
//...
}
Từ phía trên số hiệu cũng biết xem trước, chụp ảnh, ghi hình đều là thông qua bắt được thỉnh cầu kích phát, đơn thứ chụp ảnh tắc vì đơn thứ bắt được thỉnh cầu, xem trước cùng ghi hình còn lại là liên tục bắt được thỉnh cầu.
C++
RetCode StreamBase::AddRequest(std::shared_ptr<CaptureRequest>& request)
{
CHECK_IF_PTR_NULL_RETURN_VALUE(request, RC_ERROR);
request->AddOwner(shared_from_this());
request->SetFirstRequest(false);
if (isFirstRequest) {
RetCode rc = StartStream(); // khởi lưu
if (rc!= RC_OK) {
CAMERA_LOGE( "start stream [id:%{public}d] failed", streamId_);
return RC_ERROR;
}
request->SetFirstRequest(true);
isFirstRequest = false;
}
{
std::unique_lock<std::mutex> l(wtLock_);
waitingList_.emplace_back(request); // bắt được thỉnh cầu tăng thêm đến waitingList
cv_.notify_one();
}
return RC_OK;
}
Nhìn xem StreamStream là như thế nào thực hiện đi
C++
RetCode StreamBase::StartStream()
{
//...
RetCode rc = pipeline_->Prepare({streamId_}); // pipeline trước hoàn thành một ít chuẩn bị công tác
//...
state_ = STREAM_STATE_BUSY;
std::string threadName =
g_availableStreamType[static_cast<StreamIntent>(streamType_)] + "#" + std::to_string(streamId_);
handler_ = std::make_unique<std::thread>([this, &threadName] {// sáng tạo luân chuyển tuyến trình
prctl(PR_SET_NAME, threadName.c_str());
while (state_ == STREAM_STATE_BUSY) {
HandleRequest(); // xử lý bắt được thỉnh cầu
}
});
//...
rc = pipeline_->Start({streamId_}); // thông tri pipeline cùng tầng dưới chót phần cứng có thể bắt đầu ra bức
//...
return RC_OK;
}
C++
void StreamBase::HandleRequest()
{
// nếu có bắt được thỉnh cầu hạ phát, tắc rời khỏi chờ đợi trạng thái
if (waitingList_.empty()) {
std::unique_lock<std::mutex> l(wtLock_);
if (waitingList_.empty()) {
cv_.wait(l, [this] { return!(state_ == STREAM_STATE_BUSY && waitingList_.empty()); });
}
}
//...
request = waitingList_.front();
CHECK_IF_PTR_NULL_RETURN_VOID(request);
if (!request->IsContinous()) { // nếu là liên tục bắt được, tắc giữ lại một phần copy ở waitinglist
waitingList_.pop_front();
}
}
// xử lý bắt được thỉnh cầu
request->Process(streamId_);// cuối cùng thuyên chuyển phía dưới Capture tiếp lời
return;
}
C++
RetCode StreamBase::Capture(const std::shared_ptr<CaptureRequest>& request)
{
CHECK_IF_PTR_NULL_RETURN_VALUE(request, RC_ERROR);
CHECK_IF_PTR_NULL_RETURN_VALUE(pipeline_, RC_ERROR);
RetCode rc = RC_ERROR;
if (request->IsFirstOne() &&!request->IsContinous()) {
uint32_t n = GetBufferCount();
for (uint32_t i = 0; i < n; i++) {
DeliverBuffer();// đơn thứ bắt được dùng một lần hạ phát sở hữu buffer
}
} else {
do {
rc = DeliverBuffer();// liên tục bắt được mỗi lần hạ phát một cái buffer
} while (rc!= RC_OK && state_ == STREAM_STATE_BUSY);
}
if (request->NeedCancel()) {// bị hủy bỏ bắt được tắc rời khỏi
CAMERA_LOGE( "StreamBase::Capture stream [id:%{public}d] request->NeedCancel", streamId_);
return RC_OK;
}
rc = pipeline_->Config({streamId_}, request->GetCaptureSetting());// thông tri pipeline phối trí
if (rc!= RC_OK) {
CAMERA_LOGE( "stream [id:%{public}d] config pipeline failed.", streamId_);
return RC_ERROR;
}
rc = pipeline_->Capture({streamId_}, request->GetCaptureId());// nơi này capture chỉ chính là pipeline trung source node bắt đầu hồi buffer
{
std::unique_lock<std::mutex> l(tsLock_);
inTransitList_.emplace_back(request);// xử lý quá bắt được thỉnh cầu gửi ở inTransitList
}
return RC_OK;
}
Đến này khởi lưu lưu trình liền kết thúc, pipeline hồi đi lên bức thông qua OnFrame tiếp lời xử lý
C++
RetCode StreamBase::OnFrame(const std::shared_ptr<CaptureRequest>& request)
{
//...
bool isEnded = false;
if (!request->IsContinous()) {
isEnded = true;
} else if (request->NeedCancel()) {
isEnded = true;
}
{
// inTransitList_ may has multiple copies of continious-capture request, we just need erase one of them.
std::unique_lock<std::mutex> l(tsLock_);
for (auto it = inTransitList_.begin(); it!= inTransitList_.end(); it++) {
if ((*it) == request) {
inTransitList_.erase(it);// đã hồi bức thỉnh cầu, từ inTransitList xóa bỏ
break;
}
}
if (isEnded) {
// if this is the last request of capture, send CaptureEndedMessage.
auto it = std::find(inTransitList_.begin(), inTransitList_.end(), request);
if (it == inTransitList_.end()) {
std::shared_ptr<ICaptureMessage> endMessage =
std::make_shared<CaptureEndedMessage>(streamId_, request->GetCaptureId(), request->GetEndTime(),
request->GetOwnerCount(), tunnel_->GetFrameCount());
CAMERA_LOGV( "end of stream [%d], ready to send end message, capture id = %d",
streamId_, request->GetCaptureId());
messenger_->SendMessage(endMessage);
pipeline_->CancelCapture({streamId_});// nếu lần này bắt được kết thúc, tắc hủy bỏ bắt được
}
}
}
ReceiveBuffer(buffer);// tầng dưới chót phản hồi buffer đưa còn đến sinh sản đoan, cuối cùng số lượng khung hình theo đưa đến tiêu phí đoan
return RC_OK;
}
::: hljs-center
Phụ lục
:::
[^1]: linux cùng Android quan hệ - biết chăng (zhihu)
[^2]: HAL Subsystem | Android Open Source Project (google.cn)
[^3]: zh-cn/release-notes/OpenHarmony-v3.1-release.md · OpenHarmony/docs -Gitee
[^4]: OpenHarmony HDFĐiều khiển dàn giáo giới thiệu cùng điều khiển thêm tái quá trình phân tích -OpenHarmony kỹ thuật xã khu -51CTO.COM
[^5]: OpenHarmony HDFHDI cơ sở năng lực phân tích cùng sử dụng -51CTO.COM
Camera công năng xác thật quan trọng, di động nhà máy hiệu buôn nhóm mỗi lần cuộc họp báo đều sẽ trọng điểm giới thiệu bọn họ cameras.